------- android培训、java培训、期待与您交流! ----------
线程间通信:就是多个线程在操作同一个资源,但是操作的动作不同;等待唤醒机制:wait(),notify(),notifyAll();
都是用在同步中,因为要对持有监视器的线程操作,所以要使用在同步中,因为同步此案有锁。
为什么这些操作线程的方法要定义在Object类中:
停止线程:因为这些方法在操作同步中线程时, 都必须要标识它们所操作线程只有的锁,只有同一个锁上被等待的线程,可以被同一个锁上的notify唤醒,不可以对不同锁中的线程进行唤醒。
原理:结束run方法;
开启多线程运行,运行代码通常都是循环结构;只要控制住循环,就可以让run方法结束,也就是线程结束。Thread的interrupt():强制线程恢复到运行状态,这时会发生异常;
特殊情况:当线程处于冻结状态,就不会读取到标记,那么线程就不会结束。
当制定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除,这么操作会发生异常 ;
强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束,
setDaemon(true/false):将该线程标记为守护线程或用户线程,当正在运行的线程都是守护线程时,Java虚拟机退出;该方法必须在启动线程前调用;
join():当A线程执行到了B线程的.join()方法时,A就会等待.等待B线程都执行完,A才会执行;join可以用来临时加入线程执行。setPriority([1-10]):设置线程的优先级
练习1:使用等待唤醒机制,交叉执行输入输出
class Person{private String name;
private String sex;
private boolean flag = false;
public synchronized void set(String name,String sex){
if(flag)//当有两个以上输入和两个以上输出时用while判断标记,唤醒使用notifyAll()try{r.wait();}catch(Exception e){}this.name = name;this.sex = sex;flag = true;this.notify();
}
public synchronized void get(){
}if(!flag)try{r.wait();}catch(Exception e){}System.out.println(this.name+":"+this.sex);flag = false;this.notify();}
class Input implements Runnable{
private Person r;
Input(Person r){
this.r = r;
}
public void run(){
int x = 0;while(true){
if(x==0){
r.set("mike","man");
}else{
r.set("丽丽","女");
}x = (x+1)%2;
}
}}
class Output implements Runnable{
private Person r;
Output(Person r){
this.r = r;
}
public void run(){
while(true){
r.get();
}
}}
class IODemo{
public static void main(String[] args){
Person p = new Person();Input in = new Input(p);Output out = new Output(p);new Thread(in).start();new Thread(out).start();
}}
练习2:
JDK1.5中提供了多线程升级解决方案,
将同步synchronized替换成了Lock操作;
将Object中wait和notify、notifyAll替换成Condition对象,该对象可以Lock(锁)进行获取(lock.newCondition())。
在该示例中实现了本方只换醒对方操作await(),signal()。
注意:unlock释放锁的动作一定要执行(一般放在finally中)
import java.util.concurrent.locks.*;
class IODemo2{
public static void main(String[] args){
Person p = new Person();Input in = new Input(p);Output out = new Output(p);new Thread(in).start();new Thread(in).start();new Thread(out).start();new Thread(out).start();
}}
class Person{
private String name;
private String sex;
private int count = 1;
private boolean flag = false;
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)
condition_pro.await();
this.name = name;this.sex = sex;System.out.println(this.name+":"+this.count++);flag = true;condition_con.signal();
}finally{
lock.unlock();
}
}
public void get() throws InterruptedException{
lock.lock();try{
while(!flag)
condition_con.await();
System.out.println("---"+this.name+":"+this.count);flag = false;condition_pro.signal();
}finally{
lock.unlock();
}
}}
class Input implements Runnable{
private Person r;
Input(Person r){
this.r = r;
}
public void run(){
while(true){
try{
r.set(Thread.currentThread().getName());
}
catch(Exception e){
}
}
}}
class Output implements Runnable{
private Person r;
Output(Person r){
this.r = r;
}
public void run(){
while(true){
try{r.get();}catch(Exception e){}
}
}}
练习3:将线程用setDaemon方法设置成守护线程
class DaemonThread implements Runnable{
private boolean flag = true;
public void run(){
while(flag){
System.out.println(Thread.currentThread().getName()+"...run");
}
}}
class MainClass{
public static void main(String[] args){
DaemonThread dt = new DaemonThread();Thread t1 = new Thread(dt);Thread t2 = new Thread(dt);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方法练习,申请该线程加入到CPU运行中来,
class Demo implements Runnable{
public void run(){
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+"..."+i);
}
}}
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执行结束唤醒主线程;t2.start();//t1.join();//此时有t1,t2两个线程同时存在,他俩交替执行,知道t1结束,再唤醒主线程(不用考虑t2是否执行结束);for(int i = 0;i<100;i++){
System.out.println("main..."+i);
}System.out.println("over");
}}