/*
线程间的通信,等待唤醒机制,生产者消费者问题。新锁lock(): 守护线程,interrupt()停止线程用,join()yield()
*/
/*线程间通信:
其实就是多个线程在操作同一个资源。
但是操作的动作不同。
思考1:wait(),notify(),natifyAll()用来操作线程为什么定义在Object类中?
1.这些方法存在于同步中
2.使用这些方法时必须要标识所属的同步的锁
3.锁可以是任意对象。所以任意对象调用的方法一定定义在object类中
思考2.wait(),sleep()的区别?
wait():释放资源,释放锁
sleep()释放资源,不释放锁。
*/
class Res
{
String name;
String sex;
boolean flag = false;
}
class Input implements Runnable
{
private Res s = null;
Input(Res s)
{
this.s = s;
}
public void run()
{
int x = 0;
while (true)
{
synchronized(s)//同步安全的二个前提,二个线程,同一个锁。
{
if(s.flag)
try{s.wait();}catch(Exception e){}
if (x==1)
{
s.name = "mike";
s.sex = "man";
//system.out.println(s.name+s.Res);
}
else
{
s.name = "丽丽";
s.sex = "女女女女女女女";
}
x=(x+1)%2;
s.flag = true;
s.notify();
}
}
}
}
class Output implements Runnable
{
private Res s = null;
Output(Res s)
{
this.s = s;
}
public void run()
{
while (true)
{
synchronized(s){
if(!s.flag)
try{s.wait();}catch(Exception e){}
System.out.println(s.name+s.sex);
s.flag = false;
s.notify();
}
}
}
}
class InOutDemo
{
public static void main(String[] args)
{
Res s = new Res();
new Thread(new Input(s)).start();
new Thread(new Output(s)).start();
}
}
/*等待唤醒机制:
wait(),notify();
必须持有同一把锁。
*/
生产者消费者问题:
class ProducerConsumerDemo
{
public static void main(String[] args)
{
ResSoure r = new ResSoure();
Thread t1 = new Thread(new Producer(r));
Thread t2 = new Thread(new Consumer(r));
t1.start();
t2.start();
//加上t3,t4
}
}
class ResSoure
{
private String name;
private boolean flag = false;
private int count = 1;
public synchronized void set(String name)
{
while(flag)//不用if,用了while,多个生产线程时会出现全部等待。
try{wait();}catch(Exception e){}
this.name = name+"..."+count++;
System.out.println(Thread.currentThread().getName()+"--生产者--"+this.name);
flag = true;
notifyAll();
}
public synchronized void out()
{
while (!flag)
try{wait();}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"--消费者--"+this.name);
flag = false;
notifyAll();
}
}
class Producer implements Runnable
{
private ResSoure r;
Producer(ResSoure r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.set("生产者");
}
}
}
class Consumer implements Runnable
{
private ResSoure r;
Consumer(ResSoure r)
{
this.r = r;
}
public void run()
{
while(true)
{
r.out();
}
}
}
JDK1.5升级版 新锁
lock(): 获取锁 unlock():释放锁.
synchronized :释放锁是隐式过程。lock是显式的。
private Lock lock = new ReentrantLock();
private Condition condition = lock.newCondition();//可以多个
condition.await();condition.signal();
import java.util.concurrent.locks.*;
class LockDemo
{
public static void main(String[] args)
{
ResSoure r = new ResSoure();
Thread t1 = new Thread(new Producer(r));
Thread t2 = new Thread(new Consumer(r));
Thread t3 = new Thread(new Producer(r));
Thread t4 = new Thread(new Consumer(r));
t1.start();
t2.start();
t3.start();
t4.start();
//加上t3,t4
}
}
class ResSoure
{
private String name;
private boolean flag = false;
private int count = 1;
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)//不用if,用了while,多个生产线程时会出现全部等待。
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);
condition_pro.signal();
flag = false;
}
finally
{
lock.unlock();
}
}
}
class Producer implements Runnable
{
private ResSoure r;
Producer(ResSoure r)
{
this.r = r;
}
public void run()
{
while(true)
{
try
{
r.set("生产者");
}
catch (Exception e)
{
}
}
}
}
class Consumer implements Runnable
{
private ResSoure r;
Consumer(ResSoure r)
{
this.r = r;
}
public void run()
{
while(true)
{
try
{
r.out();
}
catch (Exception e)
{
}
}
}
}
停止线程
stop方法已经过时,不再推荐使用。强制停止,这是不OK的。
那么如何停止线程?
只有一种,run方法结束。
开启多线程运行,运行代码通常都是循环结构。
只要控制住循环,就可以让run方法结束,也就是线程结束。
特殊情况:
当线程处于冻结状态
就不会读取到标记,那么线程不会结束。
当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。
强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
中断方法:interrupt(),Thread类中的方法,
该方法是结束线程的冻结状态,使线程强制回到运行状态来。只有运行,才能读取标记。
当线程处于wait(),sleep()时,可以用interrupt()使线程醒过来,读取结束标记。
import java.util.*;
class Reser implements Runnable
{
private int num = 0;
boolean flag = true;
public synchronized void run()
{
while (flag)
{
try
{
wait();//线程1,2都挂在这了。因为wait()会释放锁
}
catch (InterruptedException e)
{
System.out.println("...Exception...");
flag = false;//更换条件,让线程结束。
}
System.out.println(Thread.currentThread().getName()+"......"+num++);
}
}
}
class Interrupt
{
public static void main(String[] args)
{
int count = 0;
Reser rr = new Reser();
t1.setDaemon(true);//true标记守护线程,启动前标记。
t2.setDaemon(true);
Thread t1 = new Thread(rr);
Thread t2 = new Thread(rr);
t1.start();t2.start();
while (true)
{
if ((count++) == 60)
{
//rr.flag = false;
//t1.interrupt();//唤醒,让t1回到运行状态,去运行。
//t2.interrupt();
break;
}
System.out.println(Thread.currentThread().getName() +"----"+ count);
}
}
}
守护线程:后台线程。开启后,和前台线程都抢CPU,
当所有前台线程都结束后,后台线程自动结束。
setDaemon()
public final void setDaemon(boolean on)
参数:
on - 如果为 true,则将该线程标记为守护线程。
抛出:
IllegalThreadStateException - 如果该线程处于活动状态。
SecurityException - 如果当前线程无法修改该线程。
将该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java 虚拟机退出。
该方法必须在启动线程前调用。
设置1.2二个守护线程,当主线程结束后,没有设置flag为false;线程一样结束。
---------------
join()方法:如果满足条件,临时加入进来。当线程遇到 join,就等谁执行完。
特点,当A线程执行到B线程的join方法时,a就会等待,等B执行完。
join可以用来临时加入线程执行。
toString()
返回该线程的字符串表示形式,包括线程名称、优先级和线程组。
setPriority(int newPriority)更改线程的优先级。
设置优先级,0到10。数字越大,优先级越高。
1.5.10最明显。
MAX_PRIORITY
线程可以具有的最高优先级。
使用方法。t1.setPriority(Thread.MAX_PRIORITY)
MIN_PRIORITY
线程可以具有的最低优先级
NORM_PRIORITY
分配给线程的默认优先级。
yield()暂停当前正在执行的线程对象,并执行其他线程。
Thread.yield();