Java第十四天学习笔记~多线程(线程直接通信---等待唤醒机制、多生产者多消费者问题、JDK1.5新特性、wait和sleep区别)

线程直接通信示例

//资源
class Resource
{
	String name;
	String sex;
}
//输入
class Input implements Runnable
{
	Resource r;
	Input(Resource r)
	{
		this.r=r;
	}
	public void run()
	{
		int x=0;
		while(true)
		{
			if(x==0)
			{
				r.name="mike";
				r.sex="nan";
			}
			else
			{
				r.name="丽丽";
				r.sex="女女女女女女女女女女";
			}
			x=x++%2;
			
		}
	}
}
//输出

class Output implements Runnable
{
	Resource r;
	Output(Resource r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			System.out.println(r.name+"...."+r.sex);
		}
	}
}

class ResourceDemo
{
	public static void main(String[] args)
	{
		//创建资源
		Resource r=new Resource();
		//创建任务
		Producer in=new Producer(r);
		Consumer out=new Consumer(r);
		//创建线程
		Thread t1=new Thread(in);
		Thread t2=new Thread(out);
		//开启线程
		t1.start();
		t2.start();
	}
}

等待唤醒机制

涉及的方法:

  1. wait( ):让线程处于冻结状态,被wait的线程会被存储到线程池中
  2. notify():唤醒线程池中一个线程(任意)
  3. notifyAll():唤醒线程池中的所有线程

这些方法是用于操作线程状态的方法

必须要明确到底操作的是哪个锁上的线程

为什么操作线程的方法 wait notify notifyAll  定义在了Object类中

因为这些方法是监视器方法,监视器其实就是锁,锁可以是任意对象,任意对象调用的方式一定定义在Object类中

多生产者多消费者问题

/*多生产者多消费者*/


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(InterruptedException e){};//t1  t0
		this.name=name+count;//烤鸭1  烤鸭2 烤鸭3
		count++;//2 3 4
		System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);//生产烤鸭1  生产烤鸭2 生产烤鸭3
		flag=true;
		notify();
	}
	public synchronized void out()//t3
	{
		while(!flag)
			try{this.wait();}catch(InterruptedException e){};//t2 t3
		
		System.out.println(Thread.currentThread().getName()+"...消费者..."+this.name);//消费烤鸭1
		flag=false;
		notify();
	}
}
class Producer implements Runnable
{
	private Resource r;
	Producer(Resource r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.set("烤鸭");
		}
	}
}
class Consumer implements Runnable
{
	private Resource r;
	Consumer(Resource r)
	{
		this.r=r;
	}
	public void run()
	{
		while(true)
		{
			r.out();
		}
	}
}
class ProducerConsumerDemo
{
	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(con);
		t1.start();
		t2.start();
	}
}

while标记,解决了线程换区执行权后是否要运行

notifyAll解决了,本方线程一定会唤醒对方线程

notify:只能唤醒一个线程,唤醒本方线程无意义而且while判断标记+notify会导致死锁

if判断标记:只有一次,会导致不该运行的线程运行,出现数据错误情况

JDK1.5新特性

将同步和锁封装成了对象,并将操作锁的隐式方式定义到了该对象中,将隐式动作变成了显示动作

创建一个锁对象

lock lock=new Reentrantlook();

void show()
{
    synchronized(obj)
    {
        code.....;           //同步代码块对于锁的操作是隐式的
    }
}
void show()
{
    lock.lock();    //获取锁
    code.....;
    lock.unlock();    //释放锁
}

通过已有的锁获取该锁上的监视器对象

Condition con=lock.newCondition( );

通过已有的锁获取2组监视器,一组监视生产者一组监视消费者

Condition producer_con=lock.newCondition();

Condition consumer_con=lock.newCondition();

Lock接口:出现替代了同步代码块或同步函数的隐式锁,操作变成了显示操作,同时更为灵活,可以一个锁上加上多组监视器

lock():获取锁

unlock():释放锁,通常需定义finally代码块中

Condition接口:出现代替了object中的wait notify notifyAll 方法,将这些监视器方法单独进行封装,变成condition监视器对象,可以任意锁进行组合。

await();

signal();

signalAll();

wait和sleep区别?

//sleep和wait区别
class Demo
{
	void show()
	{
		synchronized(this)
		{
			wait();//t0 t1 t2
		}
	}
	void method()
	{
		synchronized(this)
		{
			//wait();
			notifyAll();
		}//t4
	}
}
class 
{
	public static void main(String[] args)
}

1、wait可以指定时间也可以不指定

  sleep必须指定时间

2、在同步时,对CPU的执行权和锁的处理不同

wait:释放执行权,释放锁

sleep:释放执行权,不释放锁

线程的停止

run方法结束:开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让run方法结束,也就是线程结束。

特殊情况:当线程处于了冻结状态。就不会读取到标记。那么线程就不会结束。

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

强制让线程恢复到运行状态中来。这样就可以操作标记让线程结束。Thread类提供该方法 interrupt( );

Thread的其他方法

join():当A线程执行到了B线程的.join()方法时,A就会等待。等B线程都执行完,A才会执行。join可以用来临时加入线程执行。

setDaemon():将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。该方法必须在启动线程前调用。

setPriority(int newPriority):设置线程优先级,级数为1~10

yield() :暂停当前正在执行的线程对象,并执行其他线程。
 

猜你喜欢

转载自blog.csdn.net/crazyhulu/article/details/84868936