一、线程间通讯:
多个线程在操作同一个资源,但是操作的动作不同。
wait()-------notify( )---notifyAll( ) 都使用在同步中,因为要对持有监视器(锁)的线程操作。所以要使用在同步中,因为只有同步才有锁。
1、为什么这线程的方法定义在Object类中呢?
因为这些方法在操作同步线程时,都必须标识他们所操作线程只有的锁,只有同一个锁上的被等待线程,才可以被同一个锁上notify所唤醒。不可以对不同锁中的线程进行唤醒,也就是说等待和唤醒必须是同一把锁。
而锁可以是任意对象,所以可以被任意对象调用的方法定义在Object类中。
2、wait( )是一个方法,隶属于Object类
用法:publicvoid wait( ){throw new Exception( )}
在此处无法throw 只能try
二、生产者和消费者
需求:多个生产者和多个消费者,生产者生产商品,消费者消费商品
任意一个生产者生产一次,则任意一个消费者消费一次,交替进行;
思路:1、定义一个操作资源,生产者和消费者对其进行操作
其中包括两个构造函数:生产商品和消费商品
2、定义生产者实现Runnable接口以便多线程
3、定义消费者实现Runnable接口以便实现多线程、
4、创建主函数,建立两个生产者和两个消费者
class Resource
{
private String name; //声明一个name
private int count=1; //初始化序号
private Boolean flag=false; //初始化标记为假
public synchronized voidset(String name) //闯进生产商品构造函数
{
while(flag) //判断标记是否为真,若为真则在此等待标记为假的对象运行,唤醒后判断标记
try{this.wait();}catch(Exception e){ } //等待函数
this.name=name+”….”+count++; //商品名称加序号赋值给本类声明的name
System.out.println(Thread.currentThread().getName()+“..生产者..”+this.name);//获取正在执行线程对象名称加我们自定义的商品名称
flag=true;//商品生产完成将标记更改为真
this.notifyAll( );//唤醒所有正在等待的进程,
}
publicsynchronized 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 Resourse res; //声明Resource类的res
Producer(Resouece res)
{
this.res=res;
}
public void run() //创建线程,复写runnable中的run函数
{
while(true)
{
res.set(“商品”);//调用res对象中的set函数
}
}
}
class Consumer implements Runnable//穿件消费者类
{
Private Resource res;
Consumer (Resource res)
{
this.res=res;
}
public voidrun()
{
while(true)
{
res.out();
}
}
}
class ResourceDemo
{
public static voidmain(String[ ] args) //主函数
{
Resource r=new Resource();//创建资源对象
Producer p=new Producer(r);//创建生产者对象
Consumer c=new Consumer(r);//创建消费者对象
Thread p1=new Thread(p);
Thread p2=new Thread(p);
Thread c1=new Thread(c);
Thread c2=new Thread(c);
p1.start();
p2.start();
c1.start();
c2.start();
}
}
1、为什么要定义while判断标记呢?
因为让被唤醒的线程再一次判断标记
2、为什么定义notifyAll?
因为需要唤醒对方的线程。如果用notify容易出现只唤醒本线程的情况,导致程序中的所有线程都在等待。
三、1.5版本后提供了锁对象以及等待挂起封装函数
1、将同步synchroized替换成现实lock操作
2、将Object中的wait,notifyAll替换成了condition对象,该对象可以lock锁进行获取
3、在该实例中,实现了本方只唤醒对方的操作;
import java.util.concurrent.locks.*;//引入locks包
class Resource
{
private String name; //声明一个name
private int count=1; //初始化序号
private Boolean flag=false; //初始化标记为假
privateLock lock=new ReentrantLock(); //使用解锁函数建立对象
private Condition condition_pro=lock.newCondition();//建立等待解除等待对象
privateCondition condition_con=lock.newCondition();
public void set(String name) throws InterruptedException //await是抛出异常结构
{
lock.lock();//调用锁,锁住
try
{
while(flag)
condition_pro.await();//抛出异常,没有try因此要throws
this.name=name+”….”+count++; //商品名称加序号赋值给本类声明的name
System.out.println(Thread.currentThread().getName()+“..生产者..”+this.name);
flag=true;//商品生产完成将标记更改为真
condition_con.signal();//唤醒对方condition_con线程
}
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 Resourse res; //声明Resource类的res
Producer(Resouece res)
{
this.res=res;
}
public void run( ) //创建线程,复写runnable中的run函数
{
while(true)
{
try
{
res.set(“商品”);//调用res对象中的set函数
}
catch(InterruptedExceptione)
{}
}
}
}
class Consumer implements Runnable//穿件消费者类
{
Private Resource res;
Consumer (Resource res)
{
this.res=res;
}
public void run()
{
while(true)
{
try
{
res.out();
}
catch(InterruptedExceptione)
{}
}
}
}
class ResourceDemo
{
public static void main(String[ ] args) //主函数
{
Resource r=new Resource();//创建资源对象
Producer p=new Producer(r);//创建生产者对象
Consumer c=new Consumer(r);//创建消费者对象
Thread p1=new Thread(p);
Thread p2=new Thread(p);
Thread c1=new Thread(c);
Thread c2=new Thread(c);
p1.start();
p2.start();
c1.start();
c2.start();
}
}
四、线程结束
线程的结束之前使用stop方法,现在已经过时,使用另一种run方法结束。
思路:开启多线程运行,运行代码通常是循环结构,只要能够控制住循环,就可以让run方法结束,也就是线程结束。
特殊情况:当线程处于冻结状态,就不会读取到标记,程序就不会结束。
class StopThread implements Runnable
{
private booleas 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”);
}
}
}
class StopThreadDemo
{
public static void main(String[] args)
{
StopThreadst=new StopThread();
Thread t1=newThread(st);
Thread t2=newThread(st);
t1.start();
t2.start();
int num=0;
while(true)
{
if(num++=60)
{
t1.interrupt();//对冻结进行解除
t2.interrupt();
}
System.out.println(Thread.currentThread().getName()+”…..”+num);
}
System.out.println(“over”);
}
}
当没有指定的方式让冻结的线程恢复到运行状态,这时需要对冻结进行清除。强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束
Thread类提供该方法interrupt();
五、守护线程(主线程结束该线程结束)
将该线程标记为守护线程或用户线程,当正在运行的线程都是守护线程时,Java退出运行。
该方法必须在启动线程前调用。.setDaemon(true);
class StopThread implements Runnable
{
private Boolean flag=true;
public synchronized void run()
{
while(flag)
System.out.println(Thread.currentThread().getName()+”...run”);
}
class ShouHuDemo
{
public static void main(String[] args)
{
StopThread st=newStopThread();
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++==60)
break;
System.out.println(Thread.currentThread().getName()+”….”+num);
}
System.out.println(“over”);
}
}
六、Join函数
主线程让Join线程先运行:join也是一个需要抛或try的构造函数
特点:当A线程执行到了B线程的Join()方法时,就会等待,等B线程都执行完,A才会执行。
Join可用来临时加入线程。
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//Join对应函数抛出异常
{
Demo d=new Demo();
Thread d1=new Thread(d);
Thread d2=new Thread(d);
d1.start();
d1.join();//Join函数抢夺执行权,d1结束后主线程在运行
d2.start();
for(int x=0;x<100;x++)
{
System.out.println(Thread.currentThread().getName()+”…..”+x);
}
System.out.println(“over”);
}
}
七、多线程优先级、临时停止
多线程优先级即可理解为抢夺CPU执行权能力的大小,1-10,
10是MAX_PRIORITY
5是NORM_PRIORITY
1是MIN_PRIORITY
调用方式:d1.setPriority(Thread. MAX_PRIORITY);
临时停止: Thread.yield();暂停当前正在执行的线程对象,并执行其他线程
class Demo implements Runnable
{
public void run()
{
for(int x=0;x<70;x++)
{
System.out.println(Thread.currentThread().getName)+”…”+x);
Thread.yield();//临时停止
}
}
}
class YouXianDemo
{
public static void main(String[] args) // throws Exception//Join对应函数抛出异常
{
Demo d=new Demo();
Thread d1=new Thread(d);
Thread d2=new Thread(d);
d1.start();
d1.setPriority(Thread.MAX_PRIORITY);//更改d1的优先级
//d1.join();//Join函数抢夺执行权,d1结束后主线程在运行
d2.start();
for(int x=0;x<100;x++)
{
System.out.println(Thread.currentThread().getName()+”…..”+x);
}
System.out.println(“over”);
}
}