黑马程序员——10Java多线程2


------------ android培训 java培训 、期待与您交流!------------
 
1,  线程间通讯。
            其实就是多个线程在操作同一个资源, 但是操作的动作不同。
class Res {
        private String name;
        private String sex;
        private boolean flag = false;
        public synchronized void set(String name,String sex) {
                if(flag)
                        try{this.wait();}catch(Exception e){}
                this.name = name;
                this.sex = sex;
                flag = true;
                this.notify();
        }
        public synchronized void out() {
                if(!flag)
                        try{this.wait();}catch(Exception e){}
                System.out.println(name+"........"+sex);
                flag = false;
                this.notify();
        }
}
//输入输出在两个不同的run方法中操作。但应保持同步,就需要一个共有的锁。(即资源对象锁) 
class Input implements Runnable {
        private Res r ;
        Input(Res 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 Res r ;
        Output(Res r) {
                this.r = r;
        }
        public void run() {
                while(true) {
                        r.out();
                }
        }
}
class  InputOutputDemo {
        public static void main(String[] args)  {
                Res r = new Res();
                new Thread(new Input(r)).start();
                new Thread(new Output(r)).start();
        }
}
         wait();notify();notifyAll(); 都是用在同步中。因为要对持有监视器(锁)的线程操作, 只有同步才具有锁。
        操作线程的方法定义在
Object 类中,因为这些方法在操作同步线程时,都必须要标识它们所操作线程持有的锁,只有同一个锁上的被等待线程可以被同一个锁上的 notify 唤醒,不可以对不同锁中的线程进行唤醒。而锁可以是任意对象,所以可以被任意对象调用的方法定义在 Object 类中。
2,         生产者消费者问题。
class Resource {
        private String name;
        private int count = 1;
        private boolean flag = false;     
                  //  t1   t2  
        public synchronized void set(String name) {
                while(flag)
                        try{this.wait();}catch(Exception e){}         //t1(放弃资格)  t2(获取资格)
                this.name = name+"--"+count++;
                System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
                flag = true;
                this.notifyAll();
        }
        //  t3   t4  
        public synchronized void out() {
                while(!flag)
                        try{this.wait();}catch(Exception e){}         //t3(放弃资格) t4(放弃资格)
                System.out.println(Thread.currentThread().getName()+"...消费者........."+this.name);
                flag = false;
                this.notifyAll();
        }
}
class Producer implements Runnable {
        private Resource res;
        Producer(Resource res) {
                this.res = res;
        }
        public void run() {
                while(true) {
                        res.set("+商品+");
                }
        }
}
class Consumer implements Runnable {
        private Resource res;
        Consumer(Resource res) {
                this.res = res;
        }
        public void run() {
                while(true) {
                        res.out();
                }
        }
}
定义 while 判断标记,原因:让唤醒的线程再一次判断标记。
定义
notifyAll ,原因:需要唤醒对方线程,只有 notify ,容易出现只唤醒本方线程的情况,导致程序中的所有线程都等待。
图片 
 问题:notifyAll不仅唤醒了对方线程,也唤醒了本方线程来竞争资源,而我们的目的是只须唤醒对方线程即可。
         
JDK1.5 中提供了多线程升级解决方案。将同步 synchronized 替换成现实 Lock 操作。将 Object 中的 wait,notify,notifyAll, 替换成了 Condition 对象。该对象可以通过 Lock 锁进行获取。此时需要 import java.util.concurrent.locks.*
class Resource {
        private String name;
        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+"--"+count++;
                        System.out.println(Thread.currentThread().getName()+"...生产者.."+this.name);
                        flag = true;
                        condition_con.signalAll();     //只唤醒对方,使性能更优,正是1.5这个新特性的好处
                }
                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.signalAll();
                }
                finally {
                        lock.unlock();
                }
        }
}
class Producer implements Runnable {
        private Resource res;
        Producer(Resource res) {
                this.res = res;
        }
        public void run() {
                while(true)
                        try { res.set("+商品+"); } catch (InterruptedException e) { }
        }
}
class Consumer implements Runnable {
        private Resource res;
        Consumer(Resource res) {
                this.res = res;
        }
        public void run() {
                while(true)
                        try { res.out(); } catch (InterruptedException e) { }
        }
}

3,         停止线程。
        1)定义循环结束标记。
             
stop 方法已经过时。停止线程的方法只有一种, run 方法结束。开启多线程运行,运行代码通常是循环结构。只要控制住循环,就可以让 run 方法结束,也就是线程结束。
        2)
interrupt( 中断)方法。
            特殊情况:当线程处于冻结状态。就不会读取到标记,那么线程就不会结束。当没有指定的方式让冻结的线程恢复到运行状态时,这时需要对冻结进行清除。强制让线程恢复到运行状态中来,这样就可以操作标记让线程结束。
 
Thread 类提供该方法 interrupt();
 
class StopThread implements Runnable {
        private boolean flag =true;
        public  synchronnized void run() {
                while(flag) {
                        //t1,t2两个线程死到这,无法结束。
                        try{wait();}catch{
Thread.currentThread().getName()+"....exception";
                        System.out.println(Thread.currentThread().getName()+"....run");
                }
        }
        public void changeFlag() {
                flag = false;
        }
}
class  StopThreadDemo {
        public static void main(String[] args)  {
                StopThread st = new StopThread();
                Thread t1 = new Thread(st);
                Thread t2 = new Thread(st);
                //在主线程中定义t1,t2为守护线程,则 t1,t2 守护主线程,依赖于主线程。 
                // t1.setDaemon(true);    
                // t2.setDaemon(true);
                t1.start();
                t2.start();
                int num = 0;
                while(true) {
                        if(num++ == 60) {
                                st.changeFlag();
                                //中断线程,强制清除线程的冻结状态,让该线程恢复到运行状态,使之读取循环结束标记来结束线程。
                                t1.interrupt();
                                t2.interrupt();
                                break;
                        }
                        System.out.println(Thread.currentThread().getName()+"......."+num);
                }
        }
}
 
4,   线程中的其他方法:
        1)线程的
setDaemon()方法。
            守护线程(用户线程)。 t1.setDaemon(true); 希腊守护神。
            如上述3的代码中,t1,t2为守护线程,守护主线程,主线程挂了,这个守护线程也挂掉。
        2)线程的 join()方法。
              A 线程执行到 B 线程的 .join() 方法时, A 就会等待。等 B 线程都执行完, A 才会执行。 join 可以用来临时加入线程执行
       3) 
t1.setPriority(Thread.MAX_PRIORITY) 设置线程优先级,默认 5 ,最大 10 ,最小 1
       4)
Thread.yield();    // 暂停正在执行的线程, 释放执行权, 保证线程都可执行到
       5)toString();    //返回该线程的字符串表示形式,包括线程 名称、优先级和线程组

class Demo implements Runnable {
public void run() {
for(int x=0; x<70; x++) {
System.out.println(Thread.currentThread().toString()+"....."+x);
Thread.yield();     //暂停当前正在执行的线程对象,释放执行权,并执行其他线程。
}
}
}
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.setPriority(Thread.MAX_PRIORITY);     //设置t1线程的优先级为最大,即10。
t2.start();
t1.join();     //抢夺主线程的CPU的执行权。
for(int x=0; x<80; x++) {
System.out.println("main....."+x);
}
System.out.println("over");
}
}

5,多线程的实际开发应用:

1)多线程常用使用方式 ( 匿名内部类 ) 一:
new Thread() {
      public void run()   {
           for(int x=0;x<100;x++)  {
                  System.out.println(Thread.currentThread().toString()+"......"+x);
           }
      }
}.start();
 
2)多线程常用使用方式 ( 匿名内部类 ) 二:
Runnable r=newRunnable() {
            public void run()  {
             
       for(int x=0;x<100;x++)  {
                            System.out.println(Thread.currentThread().getName()+"......"+x);
                   }
            }
};
newThread(r).start();

 
    ------------ android培训 java培训 、期待与您交流 !------------
详情请查看: http://edu.csdn.net/heima   

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值