线程间通信 等待唤醒机制 wait notify notifyAll lock Condition唤醒 停止线程interrupt 守护线程setDaemon join yield

线性间通信

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

简单例子:银行,是管钱的地方,有人往里存钱,有人往外取钱,同时进行。

wait; notify();notifyAll();

都是用在同步中,因为要对持有的监视器(锁)的线程操作。

所以要使用在同步中,因为只有在同步中才具有锁。


为什么这些操作线程的方法要定义Object类中呢?

因为这些方法在操作同步中线程时,都必须要标识他们所操作线程只有的锁。

只有同一个锁上的被等待线程,可以被同一个锁上notify唤醒。

不可以对不同锁中的线程进行唤醒。

等待和唤醒必须是同一个锁。

而锁可以是任意对象,所以可以被任意对象调用的方法定义Object类中。

class Res
{
	String name;
	String sex;
	boolean flag = false;
}

class Input implements Runnable
{
	private Res r;
	Input(Res r)
	{
		this.r =r ;
	}

	public void run()
	{
		int x = 0;
		while(true)
		{
			synchronized(r)
			{

				if(r.flag)
					try{r.wait();}catch(Exception e){}
				if (x==0)
				{
				r.name = "mike";
				r.sex = "man";
				}
				else
				{
				r.name = "lily";
				r.sex = "men";
				}
				x=(x+1)%2;
				r.flag=true;
				r.notify();
			}
			
		}
	}
}

class Output implements Runnable
{
	private Res r;
	Output(Res r)
	{
		this.r =r ;
	}

	public void run()
	{
		while(true)
		{
			synchronized(r)
			{
			if (!r.flag)
				try{r.wait();}catch(Exception e){}
				System.out.println(r.name+"---"+r.sex);
				r.flag=true;
				r.notify();
			}
		}
	}
}

class Test
{
	public static void main(String[] args)
	{
		Res r = new Res();

		Input in = new Input(r);
		Output out = new Output(r);

		Thread t1 = new Thread (in);
		Thread t2 = new Thread (out);

		t1.start();
		t2.start();


	}
}

代码优化

class Res
{
	private String name;
	private String sex;
	private boolean flag = false;
	
	public synchronized void set(String name, String sex)
	{
		if (flag)
			try{this.wait();}catch(Exception e){}
		this.name = name;
		this.sex = sex;
		flag = true;
		this.notify();
	}
	public synchronized void out()
	{
		if (!flag)
			try{this.wait();}catch(Exception e){}
		System.out.println(name+"--"+sex);	

		flag = false;
		this.notify();
	}
}

class Input implements Runnable
{
	private Res r;
	Input(Res r)
	{
		this.r =r ;
	}

	public void run()
	{
		int x = 0;
		while(true)
		{
				if (x==0)
					r.set("mike","man" );
				else
					r.set("lily","men" );
				x=(x+1)%2;	
		}
	}
}

class Output implements Runnable
{
	private Res r;
	Output(Res r)
	{
		this.r =r ;
	}

	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}

class Test
{
	public static void main(String[] args)
	{
		Res r = new Res();

		new Thread(new Input(r)).start();
		new Thread(new Output(r)).start();


	}
}

当出现多个生产者和消费者同时生产东西的时候。

使用while循环,并使用notifyAll唤醒全部。

为什么要定义while判断标记。

原因:让被唤醒的线程再一次判断标记。

为什么定义notify。

因为需要唤醒对方线程。

因为只用notify,容易出现只唤醒本方线程的情况。导致程序中的所有线程都等待。

class Test
{
	public static void main(String[] args)
	{
		Resource r = new Resource();

		Producer pro =new Producer(r);
		Consumer con =new Consumer(r);

		Thread t1 =new Thread(pro); 
		Thread t2 =new Thread(pro); 
		Thread t3 =new Thread(con); 
		Thread t4 =new Thread(con); 

		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}
class Resource
{
	private String name;
	private int count=1;
	private boolean flag = false;

	public synchronized void set(String name)
	{
		while(flag)
		try{this.wait();}catch (Exception e){}
		this.name = name+"--"+count++;

		System.out.println (Thread.currentThread().getName()+"。生产者>>>"+this.name);
		flag= true;
		this.notifyAll();
	}
	public synchronized void out()
	{	
		while(!flag)
			try{this.wait();}catch(Exception e){}
		System.out.println (Thread.currentThread().getName()+"。消费者____"+this.name);
		flag=false;
		this.notifyAll();
	}
}
class Producer implements Runnable
{
	private Resource res;
	Producer(Resource res)
	{
		this.res= res;
	}
	public void run()
	{
		while(true)
		{
			res.set("+商品+");
		}
	}
}

class Consumer implements Runnable
{
	private Resource res;
		Consumer(Resource res)
		{
			this.res= res;
		}
		public void run()
		{
			while(true)
			{
				res.out();
			}
		}
}

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

将同步synchronized替换成了现实Lock操作。

将Object中的wait,notify,notifyAll,替换类Condition对象。

await代替wait,signal代替notify,signalAll代替notifyAll

condition对象可以同时支持多个对象锁,可以分别对对象进行等待和唤醒。

该对象可以Lock锁 进行获取。

finally 释放锁 一定要执行。

该示例中,实现了本方只唤醒对方的操作。

private Lock lock = new ReentrantLock ();
private Condition condition_pro = lock.newCondition();

private Condition condition_con = lock.newCondition();

import java.util.concurrent.locks.*;

class Test
{
	public static void main(String[] args)
	{
		Resource r = new Resource();

		Producer pro =new Producer(r);
		Consumer con =new Consumer(r);

		Thread t1 =new Thread(pro); 
		Thread t2 =new Thread(pro); 
		Thread t3 =new Thread(con); 
		Thread t4 =new Thread(con); 

		t1.start();
		t2.start();
		t3.start();
		t4.start();
	}
}

class Resource
{
	private String name;
	private int count=1;
	private boolean flag = false;
	private Lock lock = new ReentrantLock ();
	private Condition condition_pro = lock.newCondition();
	private Condition condition_con = lock.newCondition();

	public  void set(String name) throws InterruptedException 
	{
		lock.lock();
		try
		{
			while(flag)
				condition_pro.await();
			this.name = name+"--"+count++;

			System.out.println (Thread.currentThread().getName()+"。生产者>>>"+this.name);
			flag= true;
			condition_con.signal();
		}	
		finally 
		{
			lock.unlock();
		}
		
	}
	public  void out() throws InterruptedException
	{	
		lock.lock();
		try
		{
			while(!flag)
				condition_con.await();
			System.out.println (Thread.currentThread().getName()+"。消费者____"+this.name);
			flag=false;
			condition_pro.signal();
		}	
		finally 
		{
			lock.unlock();
		}
	}
}
class Producer implements Runnable
{
	private Resource res;
	Producer(Resource res)
	{
		this.res= res;
	}
	public void run()
	{
		while(true)
		{
			try
			{
				res.set("+商品+");
			}
			catch (InterruptedException e)
			{
			}
		}
	}
}

class Consumer implements Runnable
{
	private Resource res;
		Consumer(Resource res)
		{
			this.res= res;
		}
		public void run()
		{
			while(true)
			{
				try
				{
					res.out();
				}
				catch (InterruptedException e)
				{
				}
			}
		}
}

停止线程

停止线程,只有一种,就是run方法结束。

开启多线程运行,运行代码通常是循环结构。

只要控制循环,就可以让run方法结束,也就是线程结束。

class StopThread implements Runnable
{	
	private boolean flag =true;
	public void run()
	{

		while(flag)
		{
			System.out.println(Thread.currentThread().getName()+".....run");
		}	
	}
	public void changeFlag()
		{
			flag = false;
		}
}

class Test
{
	public static void main(String[] args)
	{
		StopThread st = new StopThread();

		Thread t1= new Thread(st);
		Thread t2= new Thread(st);
		
		t1.start();
		t2.start();

		int num = 0;

		while(true)
		{
			if(num++ ==10)
			{
				st.changeFlag();
				break;
			}
			System.out.println(Thread.currentThread().getName()+"...."+num);
		}
	}
}

interrupt(强制唤醒等待)

特殊情况

当线程处于了冻结状态。

就不会读取到标记。那么线程就不会结束。

当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结状态进行清除。

强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。

Thread提供了该方法:interrupt

class StopThread implements Runnable
{	
	private boolean flag =true;
	public synchronized void run()
	{
		while(flag)
		{
			try
			{
				wait();
			}
			catch (InterruptedException e)
			{
				System.out.println(Thread.currentThread().getName()+".....Exception");
				flag = false;
			}
			System.out.println(Thread.currentThread().getName()+".....run");
		}	
	}
	public void changeFlag()
		{
			flag = false;
		}
}

class Test
{
	public static void main(String[] args)
	{
		StopThread st = new StopThread();

		Thread t1= new Thread(st);
		Thread t2= new Thread(st);
		
		t1.start();
		t2.start();

		int num = 0;

		while(true)
		{
			if(num++ ==10)
			{
				t1.interrupt();
				t2.interrupt();
				break;
			}
			System.out.println(Thread.currentThread().getName()+"...."+num);
		}
	System.out.println("over");
	}
}
setDaemon

守护线程(跟随前台线程,只要主线程结束,守护线程跟着结束)

当正在运行的线程都是守护线程时,java虚拟机退出。

1守护线程必须在启动线程前调用。

2主线程结束,守护线程跟着结束。

class StopThread implements Runnable
{	
	private boolean flag =true;
	public  void run()
	{
		while(flag)
		{
			System.out.println(Thread.currentThread().getName()+".....run");
		}	
	}
	public void changeFlag()
		{
			flag = false;
		}
}
class Test
{
	public static void main(String[] args)
	{
		StopThread st = new StopThread();

		Thread t1= new Thread(st);
		Thread t2= new Thread(st);
		
		t1.setDaemon(true);
		t2.setDaemon(true);
		t1.start();
		t2.start();

		int num = 0;

		while(true)
		{
			if(num++ ==10)
			{
				break;
			}
			System.out.println(Thread.currentThread().getName()+"...."+num);
		}
	System.out.println("over");
	}
}
join

当A线程执行到了B线程的.join()方法时,A线程就会等待。等B线程都执行完,A才会执行。

join可以用来临时加入线程执行。

join夺取主线程权限,当join的线程运行完,才执行其他线程。

class Demo implements Runnable
{
	public void run()
	{
		for (int x=0;x<70 ;x++ )
		{
			System.out.println(Thread.currentThread().getName()+"-----"+x);
		}
	}
}

class Test
{
	public static void main(String[] args) throws Exception
	{
		Demo d = new Demo();

		Thread t1 = new Thread(d);
		Thread t2 = new Thread(d);
		
		t1.start();
		t1.join();	 //t1要主线程的执行权;
		t2.start();

		for (int x=0;x<80 ;x++ )
		{
			System.out.println("main-----"+x);
		}
	System.out.println("over");
	}
}
toString
返回该线程的字符串表示形式,包括线程名称,优先级和线程组。

Thread[Thread-0,5,main]


优先级

1-10

默认优先级是5(1优先级最小,10优先级最大)

MAX PRIORITY 10级

MIN PRIORITY 1级

NORM PRIORITY 5级

                Demo d = new Demo();

		Thread t1 = new Thread(d);
		Thread t2 = new Thread(d);
		
		t1.start();
		
		t1.setPriority(Thread.MAX_PRIORITY);

		t2.start();
yield

暂缓线程执行

Thread.yield()

可以达到减缓线程执行,可以达到线程交替运行的效果

同时运行

class ThreadTest
{
	new Thread()
	{
		public void run()
		{
			for (int x=0;x<100 ;x++ )
			{
				Syetem.out.println(Thread.currentThread().getName()+"---"+x);
							}
		}
	}.start();

	for (int x=0;x<100 ;x++ )
		{
			Syetem.out.println(Thread.currentThread().getName()+"---"+x);
		}
		
	Runnable r = new Runnable()
	{
		publiec void run()
		{
			for (int x=0;x<100 ;x++ )
			{
				Syetem.out.println(Thread.currentThread().getName()+"---"+x);
			}
		}
	};
	new Thread(r).start();
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值