黑马程序员之java线程通信学习

来源:互联网 发布:mac怎么一键回到桌面 编辑:程序博客网 时间:2024/05/01 18:44

------- 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");
}
}

------- android培训、java培训、期待与您交流! ----------

0 0
原创粉丝点击