您的位置:首页 > 编程语言 > Java开发

java多线程——调度

2016-06-04 10:12 387 查看
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框架
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: