线程直接通信示例
//资源
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();
}
}
等待唤醒机制
涉及的方法:
- wait( ):让线程处于冻结状态,被wait的线程会被存储到线程池中
- notify():唤醒线程池中一个线程(任意)
- 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() :暂停当前正在执行的线程对象,并执行其他线程。