1.线程通讯
线程通讯其实就是多个线程在操作同一个资源,但是操作的动作不同.
注意:wait();notify();notifyAll()都使用在同步中,因为要对持有监视器的线程操作,所以要使用在同步中,因为只有同步才具有锁。
线程通讯实例
/*
生产鼠标,要求生产一个销售一个
*/
class Mouse
{
private String name;
private int count=1;
private boolean b = false;
Mouse(String name)//初始化对象
{
this.name = name;
}
//定义产品类的生产功能,多过个线程去运行同一数据,需要同步
public synchronized void proc()
{
while(this.b)//当为true时,表示鼠标生产出来了,还没卖出去,需要等待
try
{
this.wait();
}
catch (Exception e)
{
}
System.out.println(name+"...生产了第...."+count+"个");
this.b = true;
this.notifyAll();//当生产出产品时,唤醒销售线程
}
public synchronized void cus()
{
while(!this.b)
try
{
this.wait();
}
catch (Exception e)
{
}
System.out.println(name+"...消费了第"+count+"个");
count++;
this.b=false;
this.notifyAll();//销售后唤醒生产线程
}
}
//建立产品对象
class Proc implements Runnable
{
Mouse m = null;
Proc(Mouse m)
{
this.m=m;
}
public void run()
{
while(true)
{
m.proc();
}
}
}
class Cus implements Runnable
{
Mouse m = null;
Cus(Mouse m)
{
this.m=m;
}
public void run()
{
while(true)
{
m.cus();
}
}
}
class ProcCusDemo
{
public static void main(String[] args)
{
Mouse m = new Mouse("鼠标");
Proc p = new Proc(m);
Cus c = new Cus(m);
Thread t1 = new Thread(p);
Thread t2 = new Thread(c);
Thread t3 = new Thread(p);
Thread t4 = new Thread(c);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
2.中断线程
通过让run方法结束可以停止线程,需要在run方法中定义一个结束标记,但是如果线程处于了冻结状态,就无法读取结束标记,线程就不会结束,这时需要使用interrupt()对线程的冻结状态进行清除.
interrupt():如果线程在调用Object类的wait()、join()、sleep(long)方法过程中受阻,则其中断状态将被清除(使线程恢复到运行状态),它还将收到一个InterruptedException.
3.守护线程
setDaemon():将该线程标记为守护线程或用户线程,守护线程就相当于后台线程,当前台线程结束时,后台线程跟着也结束.
class StopThread implements Runnable
{
public void run()//原本run方法是一个死循环,但是将线程定义为守护线程后,主线程结束,访问run方法的线程立即也结束了
{
while(true)
{
System.out.println(Thread.currentThread().getName()+"....run");
}
}
}
class StopThreadDemo
{
public static void main(String[] args)
{
StopThread st = new StopThread();
Thread t1 = new Thread(st);
Thread t2 = new Thread(st);
//将t1,t2定义为守护线程
t1.setDaemon(true);
t2.setDaemon(true);
t1.start();
t2.start();
int num = 0;
while(true)
{
if(num++ == 60)
{
break;
}
System.out.println(Thread.currentThread().getName()+"......."+num);
}
System.out.println("over");
}
}
4.join()
join()其实就是抢夺cpu的执行权,当A线程执行到了B线程的.join()方法时,A就会等待,等B线程都执行完,A才会继续执行.
class Demo implements Runnable
{
public void run()
{
for(int x=0; x<70; x++)
{
System.out.println(Thread.currentThread().getName()+"....."+x);
}
}
}
class JoinDemo
{
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获取cpu的执行权,主线程处于冻结状态,只有t1结束主线程才能恢复运行状态
t2.start();
//t1.join();主线程冻结,t1,t2交替运行,t1结束,主线程才继续
for(int x=0; x<80; x++)
{ }
System.out.println("over");
}
}
学习感悟
个人感觉多线程这还是比较抽象的,虽然之前是学理科的,但还是很难理解线程之间的运行模式.线程的通信是一个重点,多个线程操作同一个数据,要保证先有输入才能输出,需要定义一个标示去告诉线程当前有无输入数据,有则停止输入线程开启输出线程,无则停止输出开启输入线程.