java多线程——调度

java多线程的调度问题可以分为以下几个问题:
1.设置线程优先级,
2.使用线程合并;
3.线程间通信;
4.线程闭锁与栅栏。
具体分析:
1.线程优先级
java线程优先级高的可以获得更多的运行机会,但线程的优先级是无法保障线程的执行次序的,优先级只是提高了优先级高的线程获取 CPU 资源的概率。也就是说,这个方法不靠谱。
java线程优先级用1~10表示,10表示最高优先级,1表示最低优先级,默认取值5。
线程的优先级有继承关系,如果A线程中创建了B线程,那么B将和A具有相同的优先级。
2.线程合并
线程合并就是使用join()方法, 这个方法可以有效地进行线程调度,但却只能局限于等待一个线程的执行调度。如果要等待 N 个线程的话,显然是无能为力了。而且等待线程必须在被等待线程消亡后才得到继续执行的指令,无法做到两个线程真正意义上的并发,灵活性较差。
3.线程间通信
也就是wait()和notify()方法(属于java.lang.Object),java多线程——阻塞与唤醒 中的第4点,就是介绍的这个方法,使用的是“生产者与消费者模式”。
4.线程闭锁与栅栏
//csdn有个讲的很好的博客,在这放个链接 java多线程并发系列之闭锁(Latch)和栅栏(CyclicBarrier)//
闭锁就是一扇门,在大门打开之前,所有的线程都被关在门外,也就是所有线程都被阻塞,当大门打开时,所有的线程都可以通过了,也就是所有的线程都处于可执行状态。但是,一旦大门打开了,所有的线程都能通过了,那么大门的状态只能是打开的状态,即闭锁的状态是一次性的,它必须保证在大门打开之前所有的线程都要完成。
栅栏类似于闭锁,它能阻塞一组线程直到某个事件发生。
区别:闭锁用于所有线程等待一个外部事件的发生;栅栏则是所有线程相互等待,直到所有线程都到达某一点时才打开栅栏,然后线程可以继续执行。
通过代码来加深印象:
(1)先来看闭锁的程序

//闭锁
class Cook implements Runnable{
    String name;
    CountDownLatch downLatch;
    public Cook(String name, CountDownLatch downLatch) {
        this.name = name;
        this.downLatch = downLatch;
    }
    @Override
    public void run() {
        System.out.println("厨师在做: "+name);
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println(name+"做好了。");
        downLatch.countDown();
    }
}

class Salesman implements Runnable{
    CountDownLatch downLatch;
    public Salesman(CountDownLatch downLatch) {
        this.downLatch = downLatch;
    }
    @Override
    public void run() {
        System.out.println("售货员正在等厨师干完活......");
        try {
            downLatch.await();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
         System.out.println("厨师做好食物了,售货员开始卖了。");
    }
}

public static void main(String[] args) {
    //测试闭锁
         ExecutorService executor = Executors.newCachedThreadPool();
         CountDownLatch latch = new CountDownLatch(3);
         Cook c1 = new Cook("馒头",latch);
         Cook c2 = new Cook("包子",latch);
         Cook c3 = new Cook("面包",latch);
         Salesman sman = new Salesman(latch);
         executor.execute(c3);
         executor.execute(c2);
         executor.execute(c1);
         executor.execute(sman);
         executor.shutdown();
}
/*
运行结果为:
厨师在做: 面包
厨师在做: 包子
厨师在做: 馒头
售货员正在等厨师干完活......
面包做好了。
馒头做好了。
包子做好了。
厨师做好食物了,售货员开始卖了。
*/

栅栏的程序

//栅栏
class Food implements Runnable {
    CyclicBarrier cyclicBarrier ;
    String name ;
    public Food(CyclicBarrier cyclicBarrier,String name){
           this .name =name;
           this .cyclicBarrier =cyclicBarrier;
   }
    @Override
    public void run() {
          System. out .println(name +"正在被上锅蒸,好热……" );
           try {
                 Thread. sleep(5000);
                 System. out .println(name +"不容易,终于熟了。。。。" );
                  cyclicBarrier .await();
          } catch (Exception e) {
                 e.printStackTrace();
          }
          System. out .println(name +":其他小伙伴也熟了,完了,要被吃了》-《!" );
   }
}

public static void main(String[] args) {
    //测试栅栏
         ExecutorService executorpool=Executors. newFixedThreadPool(3);
         CyclicBarrier cyclicBarrier= new CyclicBarrier(3);
         Food f1= new Food(cyclicBarrier, "包子" );
         Food f2= new Food(cyclicBarrier, "馒头" );
         Food f3= new Food(cyclicBarrier, "面包" );
         executorpool.execute(f1);
         executorpool.execute(f2);
         executorpool.execute(f3);
         executorpool.shutdown();
}
/*
运行结果为:
包子正在被上锅蒸,好热……
馒头正在被上锅蒸,好热……
面包正在被上锅蒸,好热……
包子不容易,终于熟了。。。。
馒头不容易,终于熟了。。。。
面包不容易,终于熟了。。。。
面包:其他小伙伴也熟了,完了,要被吃了》-《!
包子:其他小伙伴也熟了,完了,要被吃了》-《!
馒头:其他小伙伴也熟了,完了,要被吃了》-《!
*/

例子中的executors是Executor框架,指java 5中引入的一系列并发库中与executor相关的一些功能类,其中包括线程池,Executor,Executors,ExecutorService,CompletionService,Future,Callable等。具体可以看看这篇博文:java并发编程-Executor框架

猜你喜欢

转载自blog.csdn.net/levi_moon/article/details/51583109