黑马程序员——多线程

-----------android培训java培训、java学习型技术博客、期待与您交流!------------  

一,概述

1, 进程

        是一个正在执行的程序。

        每一个进程执行都有一个执行顺序。该顺序是一个执行路径,或者叫一个控制单元。

2,线程

         就是进程中的一个独立的控制单元。线程在控制着进程的执行。只要进程中有一个线程在执行,进程就不会结束。

        一个进程中至少有一个线程。

3,多线程存在的意义

        多线程的出现能让程序产生同时运行效果。可以提高程序执行效率。


二,创建线程的方式

方式一:继承
就是通过继承Thread类,然后复写其run方法的方式来创建线程。

步骤:

        a,定义类继承Thread

        b,复写Thread中的run方法。

             目的:将自定义代码存储在run方法中,让线程运行。

        c,创建定义类的实例对象。相当于创建一个线程。

        d,用该对象调用线程的start方法。该方法的作用是:启动线程,调用run方法。

注:如果对象直接调用run方法,等同于只有一个线程在执行,自定义的线程并没有启动。


示例:

public class thread_text {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		
		new Thread(new lineone()).start();//创建线程并启动
		new Thread(new linetwo()).start();
		
	}
	public synchronized void print(Object obj){
		System.out.println(obj);
	}
	
}
class lineone implements Runnable
{
	public void run()//覆盖run方法,方法内为线程要执行的代码
	{
		long begin=System.currentTimeMillis();
		for(int k=0;k<100;k++){
			System.out.println("*********"+k);
		}
		long end=System.currentTimeMillis();
		System.out.println(end-begin);
	}
}
class linetwo implements Runnable{
	public void run(){
		long begin=System.currentTimeMillis();
		for(int k=0;k<100;k++){
			System.out.println("---------"+k);
		}
		long end=System.currentTimeMillis();
		System.out.println(end-begin);
	}
}



方式二:实现
实现Runnable接口,并复习其中run方法的方式。

步骤:

        a,定义类实现Runnable的接口。

        b,覆盖Runnable接口中的run方法。目的也是为了将线程要运行的代码存放在该run方法中。

        c,通过Thread类创建线程对象。

        d,将Runnable接口的子类对象作为实参传递给Thread类的构造方法。


示例:

public class threaddemo {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		
		new Thread(new newline()).start();//Runnable接口子类对象作为参数传递给Thread类构造函数并调用start方法启动线程。
	}

}
class newline implements Runnable//实现Runnable接口  
{  
          
    public void run()//覆盖接口run方法   放入要被线程执行的代码。  
    {               
        int x=0;  
        while(x<10)  
        {  
            System.out.println("我是新线程");  
              x++;
        }  
          
    }  
  
  
}  


三,两种方式的区别与线程的状态


  继承Thread:线程代码存放在Thread子类run方法中。

        实现Runnable:线程代码存放在接口子类run方法中。      


几种状态:

        被创建:等待启动,调用start启动。

         运行状态:具有执行资格和执行权。

         临时状态(阻塞):有执行资格,但是没有执行权。

         冻结状态:遇到sleeptime)方法和wait()方法时,失去执行资格和执行权,sleep方法时间到或者调用notify()方法时,获得执行资格,变为临时状态。

         消忙状态:stop()方法,或者run方法结束。


四,线程的安全

1,多个线程同时访问共享数据时,会出现安全问题

2, 解决办法——线程同步

        对多条操作共享数据的语句,只能让一个线程都执行完。在执行过程中,其他线程不可以参与执行。

有两种解决方式,一种是同步代码块,还有就是同步函数。都是利用关键字synchronized来实现。

 a,同步代码块

        用法:

                  synchronized(对象)

                  {需要被同步的代码}


  b,同步函数

        格式:

                在函数上加上synchronized修饰符即可。


同步的前提

        a,必须要有两个或者两个以上的线程。

        b,必须是多个线程使用同一个锁。

3,同步的利弊

        好处:解决了多线程的安全问题。

        弊端:多个线程需要判断锁,较为消耗资源。


4,线程的锁
同步函数使用的锁是this
静态函数所使用的锁是该方法所在类的字节码文件对象。类名.class

五,死锁

 当同步中嵌套同步时,就有可能出现死锁现象。
示例:

public class threaddemo3//死锁练习。
{

		public static void main(String[] args) {
			
			new Thread(new Test(true)).start();
			new Thread(new Test(false)).start();
			
		}
	}


	class Test implements Runnable
	{
		private boolean flag;
		Test(boolean flag)
		{
			this.flag=flag;
		}

		public void run()
		{
			if(flag)
			{
				while(true)
				{
					synchronized(ownlock.locka)
					{   System.out.println("if heima a");
						synchronized(ownlock.lockb)
						{
							System.out.println("if heima b");
						}
					}
				}
				
				
			}
			else
			{
				while(true)
				{
					synchronized(ownlock.lockb)
					{   System.out.println("else heima b");
						synchronized(ownlock.locka)
						{
							System.out.println("else heima a");
						}
					}
				}
				
			}
			
		}
		
	}

	class ownlock// 此类用于提供锁 。	
	{
		static Object locka = new Object();
		static Object lockb = new Object();
	}


六,线程间通信

就是多个线程在操作同一个资源,但是操作的动作不同。
示例:

public class thread_text2 {

	/**
	 * @param args
	 */
	public static void main(String[] args) {
		// TODO Auto-generated method stub
		resource a=new resource();
		new Thread(new threadset(a)).start();//启动线程
		new Thread(new threadget(a)).start();
	}

}
class threadget implements Runnable//获取资源线程
{	
	resource r=null;
	threadget(resource b)//自定义构造方法,接受资源对象
	{
	this.r=b;
	}
	public void run(){
		while(true){
		r.getOutput();
		}
	}
}
class threadset implements Runnable//存储资源线程
{	
	resource r=null;
	
	threadset(resource b){
		this.r=b;
	}
	
	
	public void run(){
		while(true){
	r.setInPut("异界的旅行者","man",22);
		}
	}
	
}


class resource //资源
{
	private String name;
	private String sex;
	private int age;
	boolean f=false;
	public String toString()//重写toString方法
	{
		return ("name:"+name+"	sex:"+sex+"		age:"+Integer.toString(age));
	}
	public synchronized void setInPut(String str,String sex,int age)
	{
		
		if(f){
			try{wait();}catch(Exception e){}
		}
		
		this.name=str;
		this.sex=sex;
		this.age=age;
		f=true;
		System.out.println("存"+toString());
		notify();//唤醒
	}
	public synchronized void getOutput()
	{
		if(!f){
			try{wait();}catch(Exception e){}
		}
		System.out.println("取"+toString());
		f=false;
		notify();
	}
}




JDK1.5中提供了多线程升级解决方案。

        将同步synchronized替换成显示的Lock操作。将ObjectwaitnotifynotifyAll,替换成了Condition对象。该Condition对象可以通过Lock锁进行获取,并支持多个相关的Condition对象。

Lock:替代了Synchronized
lock(); 
unlock();
newCondition();

Condition:替代了Object  wait  notify  notifyAll
await();
signal();
signalAll();







你可能感兴趣的:(java基础)