线程间的通讯:对资源的操作动作不同,比如说两个卡车一个拉煤一个装煤,但是他们共享了一个资源。
怎么样把这个资源拿出来?怎样把车装满?这个资源当然是一个类,他里面的组成元素就是对象!!现在我们就要有操作对象的思想了,用对象把这车装满,现在一车装一个对象。
等待唤醒机制;
用的不是sleep是wait。flag标记,这是两人沟通的方式。其实每个标记就要做一次等待或者notify,判断wait,改值notify。线程池。notify唤醒里面的线程,按顺序唤醒。wait和notify必须用在同步上,r其实是监视器。必须标识锁。任意对象能调用的方法当然定义在object上。watinotify,notifyall因为要对持有监视器的线程操作,所以要使用同步中,因为只有同步才具有锁。只有容易锁上被等待的线程,才可以被唤醒。也就是说,等待和唤醒必须是同一个锁,。
代码优化,把这段代码简化。非静态方法的同步锁匙this。。。。静态才是类名.class
原理:匿名对象,第二个把属于资源的操作,比如加料,输出,放在资源这个类上,车子负责调用就行了。
生产消费这例子。
生产粮食的同时,也在吃粮食,是个经典的协作多线程
import java. util. Random;
//仓库部分,是生产者和消费者的共享资源
class Stage
{
Random rand= new Random() ;
private int size;
private int count;
public void setSize (int size ){this .size =size ;}
public void setCount (int count ){this .count =count ;}
public int getSize (){return size; }
public int getCount (){return count; }
public String
toString(){ return "仓库大小:" +size +"\t剩余:" +count +"。" ;}
public boolean flag= false;
public synchronized void push ()
{
while (flag )
try {wait (); }
catch (Exception e ){}
int temp= rand. nextInt( size- count );
System . out. println( toString ()+ Thread. currentThread() .getName ()+ ",准备生产:" +temp );
count+= temp;
flag= true;
notifyAll ();
}
public synchronized void pop ()
{
while (! flag)
try {wait (); }
catch (Exception e ){}
int temp= rand. nextInt( count );
System . out. println( toString ()+ Thread. currentThread() .getName ()+ ",准备消费:" +temp );
count= count- temp;
flag= false;
notifyAll ();
}
}
//生产者部分
class Productor implements Runnable {
// TODO Auto-generated method
stub
private Stage s ;
Productor ( Stage s){ this. s= s; }
public void run () {
while (true )
s. push ();
}
}
//消费者部分
class Consummer implements Runnable {
private Stage s ;
Consummer ( Stage s){ this. s= s; }
public void run () {
// TODO Auto-generated method
stub
while (true )
s. pop ();
}
}
public class MyThreadTest {
public static void main ( String[] args ) {
// TODO Auto-generated method
stub
;
Stage s =new Stage ();
s .setSize ( 80) ;
s .setCount ( 10) ;
new Thread( new Productor( s ) ). start ();
new Thread( new Productor( s ) ). start ();
new Thread( new Consummer( s ) ). start ();
new Thread( new Consummer( s ) ). start ();
}
} //打印结果
/*仓库大小:80 剩余:69。Thread-1,准备生产:2
仓库大小:80 剩余:71。Thread-2,准备消费:51
仓库大小:80 剩余:20。Thread-1,准备生产:47
仓库大小:80 剩余:67。Thread-3,准备消费:49
仓库大小:80 剩余:18。Thread-0,准备生产:16
仓库大小:80 剩余:34。Thread-3,准备消费:30
仓库大小:80 剩余:4。Thread-1,准备生产:31
仓库大小:80 剩余:35。Thread-2,准备消费:14
仓库大小:80 剩余:21。Thread-1,准备生产:26
仓库大小:80 剩余:47。Thread-3,准备消费:34
.
.
.
*/
多线程其他常见操作
jdk5.0升级版后换成了lock和condition。显式的锁和显示的唤醒机制,一个锁对应多个condition,不懂的看看api。其实就是Condition
condition_pro=lock.condition();
Lock lock
为什么newreen。。(关键是要try和finally)(新建一个多重锁~)
怎么停止循环(线程)?原理只有一种,停止run,要开启多线程的通常都是循环结构,只要控制了循环就能结束。
强制做这件事情,如果调用冻结状态,结果被冻结了,强制清除冻结状态。interrupt//。清除冻结状态。。。发生异常了,人家不该醒,你让人家醒了。怎么让程序结束呢?在catch里面加入改变flag的语句,强制让线程回到运行状态来,就可以操作标记让线程结束。
守护线程
程序怎么结束了?后台线程,当前台线程都结束时,后台线程会自动结束。当一个线程依赖另一个线程时,可以通过将线程标志成setdaemon;必须在线程启动前标3f记。
join
加入。join也是抛出异常。join的意思就是说,t1申请要cpu的执行权,住线程被冻结,t1结束了就能回来。等待t1执行完才能执行,临时加入线程,让这段线程执行完再执行。碰到谁的join就等谁死。当A线程执行到B线程的jion时,a就等待到b执行完。b要是wait呢?
toString:覆盖了obj的tostring。
优先级,线程组是个对象,把你new的线程对象放里面就行了。但是用的频率很低。优先级表示抢资源的能力,默认都是5.一共就10级,5和10
没啥区别。
yeile,暂停当前线程对象执行其他对象。会是多线程,一人执行一次。
开发的时候怎么写线程呢?
当某些代码需要同时被执行时,匿名内部类。。。独立运算不相干代码的时候
他们并不是协同的时候可以用,这个时候可以继承thread,另外Runnable是不能创对象的,必须thread引用指向runnable;