Java基础第十二天学习日记_线程、线程的同步、线程间通讯

来源:互联网 发布:redis集群数据同步问题 编辑:程序博客网 时间:2024/05/31 19:43
------- android培训、java培训、期待与您交流! ----------

线程间通信:其实就是多个线程在操作同一个资源,但是操作的动作不同。

思考的问题:1.wait(),notify(),notifyAll(),用来操作线程为什么定义在了Object类中?

  答:1、这些方法存在于同步中。

         2、使用这些方法时必须要标识所属的同步的锁。只有同一个锁上的被等待线程,可以被同一个锁的notify唤醒。不可以对不同锁中的线程进行唤醒。也就是说,等待和唤醒必须是同一个锁。

         3、锁可以是任意对象,所以任意对象调用的方法一定定义在Object类中。

2、wait()、sleep()有什么区别?

  答:wait():释放资源,释放锁。

         sleep():释放资源,不释放锁。

等待唤醒机制:

等待的线程都会保存在内存的线程池中,唤醒时,如无特殊的说明,唤醒的就是线程池中第一个等待的线程。

public class InputOutputDemo {public static void main(String[] args) {Res r=new Res();Input in=new Input(r);Output out=new Output(r);Thread t1=new Thread(in);Thread t2=new Thread(out);t1.start();t2.start();}}class Res{String name;String sex;boolean flag=false;}class Input implements Runnable{private Res r;Input(Res r){this.r=r;}public void run(){int x=0;while(true){synchronized(r){if(r.flag)try{r.wait();}catch(Exception e){}//wait和notify方法必须标明是那个锁对象,这样才能明白要等待唤醒哪个线程。if (x==0){r.name="zhangsan";r.sex="man";}else{r.name="lisi";r.sex="woman";}x=(x+1)%2;r.flag=true;try{r.notify();}catch(Exception e){}}}}}class Output implements Runnable{private Res r;Output(Res r){this.r=r;}public void run(){while(true){synchronized (r){if(!r.flag)try{r.wait();}catch(Exception e){}System.out.println(r.name+"-----"+r.sex);r.flag=false;try{r.notify();}catch(Exception e){}}}}}
public class InputOutputDemo2 {public static void main(String[] args) {Res1 r=new Res1();Thread t1=new Thread(new Input1(r));Thread t2=new Thread(new Output1(r));t1.start();t2.start();}}class Res1{private String name;private String sex;private boolean flag=false;public synchronized void set(String name,String sex){if(flag)try{this.wait();}catch(InterruptedException e){}this.name=name;this.sex=sex;flag=true;this.notify();}public synchronized void out(){if(!flag)try{this.wait();}catch(InterruptedException e){}System.out.println(name+"-----"+sex);flag=false;this.notify();}}class Input1 implements Runnable{private Res1 r;Input1(Res1 r){this.r=r;}public void run(){int x=0;while(true){if(x==0)r.set("zhangsan","man");elser.set("lisi","woman");x=(x+1)%2;}}}class Output1 implements Runnable{private Res1 r;Output1(Res1 r){this.r=r;}public void run(){while(true){r.out();}}}

 

JD1.5中提供了多线程升级解决方案。将同步Synchronized替换成实现Lock操作。将Object中的wait,notify,notifyAll,替换成了condition对象。该对象可以Lock锁进行获取。

package day12;import java.util.concurrent.locks.Condition;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ProducerCustomerDemo2 {public static void main(String[] args){Resource1 r=new Resource1();Producer1 p=new Producer1(r);Customer1 c=new Customer1(r);Thread t1=new Thread(p);Thread t2=new Thread(p);Thread t3=new Thread(c);Thread t4=new Thread(c);t1.start();t2.start();t3.start();t4.start();}}class Resource1{private String name;private int count;private boolean flag=false;private Lock lock=new ReentrantLock();//1.5版本新特性。相当与synchronized语句。//private Condition condition=lock.newCondition();//Condition相当与监视器方法,由lock的newCondition()方法获取。private Condition condition_pro=lock.newCondition();//每个lock可以建立多个condition,它们可以互相等待唤醒。private Condition condition_cus=lock.newCondition();public void set(String name)throws InterruptedException{lock.lock();//上锁try{while(flag)condition_pro.await();//由await()替换wait()方法this.name=name+"----"+count++;System.out.println(Thread.currentThread().getName()+"...生产者。。。"+this.name);flag=true;condition_cus.signal();//由signal()替换notify(),由signalAll()替换notifyAll()}finally{lock.unlock();}} public void out()throws InterruptedException{lock.lock();try{while(!flag)condition_cus.await();System.out.println(Thread.currentThread().getName()+"...消费者。。。。。。。。"+this.name);flag=false;condition_pro.signal();}finally{lock.unlock();}}}class Producer1 implements Runnable{private Resource1 r;Producer1(Resource1 r){this.r=r;}public void run(){while(true){try{r.set("商品");}catch(InterruptedException e){}}}}class Customer1 implements Runnable{private Resource1 r;Customer1(Resource1 r){this.r=r;}public void run(){while(true){try{r.out();}catch(InterruptedException e){}}}}

停止线程:

1、定义循环结束标记

因为线程运行代码一般都是循环,只要控制了循环即可。

2、使用interrupt(中断)方法。

该方法是结束线程的冻结状态,使线程回到运行状态中来。

public class InterruptDemo {/** * 线程的终止 */public static void main(String[] args){StopThread st=new StopThread();     Thread t1=new Thread(st);Thread t2=new Thread(st);                                                                                        t1.start();t2.start();int num=0;while(true){if(num++==60){t1.interrupt();//中断线程的冻结状态。跟notify/signal的区别是这是强制中断的,中断后抛出异常。t2.interrupt();break;}System.out.println(Thread.currentThread().getName()+"...."+num);}}}class StopThread implements Runnable{private boolean 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");}}}

一些有用的方法:

1、setDaemon(boolean)该线程标记为守护线程或用户线程。当正在运行的线程都是守护线程时,Java虚拟机退出。该方法必须在分启动线程前调用。前台线程一结束,则守护线程也结束。

2、join()等待该线程终止。当A线程执行到了B线程的join()方法时,A就会等待。等B线程都执行完,A才会执行。join可以用来临时加入线程执行。

3、toString打印出当前线程的字符串表示形式,也就是更加详细的信息,有线程名称,线程优先级,线程所属的线程组。一般谁开启了这个线程,那么这个线程便属于那个线程组。

优先级表示cpu的执行频率,优先级越大执行频率越高。

4、setPriority(Thread.MAX_PRIORITY);设置线程的优先级(1-10)。

5、yield();暂停当前正在执行的线程对象,并执行其他线程。

------- android培训、java培训、期待与您交流! ----------  详细请查看:http://edu.csdn.net/heima/
原创粉丝点击