精华内容
参与话题
问答
  • C++11多线程编程

    千人学习 2018-09-06 14:34:58
    本课程,讲解的重点定位在c++11新标准中的多线程开发部分,同时,老师还会结合自己的经验把多线程的讲解进一步拓展到一个比较大的范畴,因为无论是c++11多线程开发还是各种其他的多线程开发实现方法,都有很多类似的...
  • 1.章节结构图 ...多线程编程一方面有助于提高系统吞吐量、提高系统的响应性、充分利用多核处理器、最小化对系统资源的使用和简化程序的结构;另一方面面临线程安全、线程活性、上下文切换和可靠性等问题 ...

    1.章节结构图

    2. 详细描述

    • 进程是程序的运行实例,一个进程可包含多个线程,他们都共享所在进程的资源;
    • 应用程序负责创建线程与启动线程,线程调度器负责线程的调度与执行;
    • 线程是多线程编程的基本单位。多线程编程一方面有助于提高系统吞吐量、提高系统的响应性、充分利用多核处理器、最小化对系统资源的使用和简化程序的结构;另一方面面临线程安全、线程活性、上下文切换和可靠性等问题
    展开全文
  • 通过前面几篇的学习,我们知道创建线程的方式有两种,一种是实现Runnable接口,另一种是继承Thread,但是这两种方式都有个缺点,那就是在...,是的,从JAVA SE 5.0开始引入了Callable和Future,通过它们构建的线程,在

    通过前面几篇的学习,我们知道创建线程的方式有两种,一种是实现Runnable接口,另一种是继承Thread,但是这两种方式都有个缺点,那就是在任务执行完成之后无法获取返回结果,那如果我们想要获取返回结果该如何实现呢?还记上一篇Executor框架结构中提到的Callable接口和Future接口吗?,是的,从JAVA SE 5.0开始引入了Callable和Future,通过它们构建的线程,在任务执行完成后就可以获取执行结果,今天我们就来聊聊线程创建的第三种方式,那就是实现Callable接口。


    1.Callable<V>接口
    我们先回顾一下java.lang.Runnable接口,就声明了run(),其返回值为void,当然就无法获取结果了。
    public interface Runnable {
        public abstract void run();
    }
    而Callable的接口定义如下
    public interface Callable<V> { 
          V   call()   throws Exception; 
    } 
    该接口声明了一个名称为call()的方法,同时这个方法可以有返回值V,也可以抛出异常。嗯,对该接口我们先了解这么多就行,下面我们来说明如何使用,前篇文章我们说过,无论是Runnable接口的实现类还是Callable接口的实现类,都可以被ThreadPoolExecutor或ScheduledThreadPoolExecutor执行,ThreadPoolExecutor或ScheduledThreadPoolExecutor都实现了ExcutorService接口,而因此Callable需要和Executor框架中的ExcutorService结合使用,我们先看看ExecutorService提供的方法:
    <T> Future<T> submit(Callable<T> task);
    <T> Future<T> submit(Runnable task, T result);
    Future<?> submit(Runnable task);
    第一个方法:submit提交一个实现Callable接口的任务,并且返回封装了异步计算结果的Future。
    第二个方法:submit提交一个实现Runnable接口的任务,并且指定了在调用Future的get方法时返回的result对象。
    第三个方法:submit提交一个实现Runnable接口的任务,并且返回封装了异步计算结果的Future。
    因此我们只要创建好我们的线程对象(实现Callable接口或者Runnable接口),然后通过上面3个方法提交给线程池去执行即可。还有点要注意的是,除了我们自己实现Callable对象外,我们还可以使用工厂类Executors来把一个Runnable对象包装成Callable对象。Executors工厂类提供的方法如下:
    public static Callable<Object> callable(Runnable task)
    public static <T> Callable<T> callable(Runnable task, T result)
    2.Future<V>接口
    Future<V>接口是用来获取异步计算结果的,说白了就是对具体的Runnable或者Callable对象任务执行的结果进行获取(get()),取消(cancel()),判断是否完成等操作。我们看看Future接口的源码:
    public interface Future<V> {
        boolean cancel(boolean mayInterruptIfRunning);
        boolean isCancelled();
        boolean isDone();
        V get() throws InterruptedException, ExecutionException;
        V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException;
    }
    方法解析:
    V get() :获取异步执行的结果,如果没有结果可用,此方法会阻塞直到异步计算完成。
    V get(Long timeout , TimeUnit unit) :获取异步执行结果,如果没有结果可用,此方法会阻塞,但是会有时间限制,如果阻塞时间超过设定的timeout时间,该方法将抛出异常。
    boolean isDone() :如果任务执行结束,无论是正常结束或是中途取消还是发生异常,都返回true。
    boolean isCanceller() :如果任务完成前被取消,则返回true。
    boolean cancel(boolean mayInterruptRunning) :如果任务还没开始,执行cancel(...)方法将返回false;如果任务已经启动,执行cancel(true)方法将以中断执行此任务线程的方式来试图停止任务,如果停止成功,返回true;当任务已经启动,执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时返回false;当任务已经完成,执行cancel(...)方法将返回false。mayInterruptRunning参数表示是否中断执行中的线程。
    通过方法分析我们也知道实际上Future提供了3种功能:(1)能够中断执行中的任务(2)判断任务是否执行完成(3)获取任务执行完成后额结果。
    但是我们必须明白Future只是一个接口,我们无法直接创建对象,因此就需要其实现类FutureTask登场啦。
    3.FutureTask类
    我们先来看看FutureTask的实现
    public class FutureTask<V> implements RunnableFuture<V> {
    FutureTask类实现了RunnableFuture接口,我们看一下RunnableFuture接口的实现:
    public interface RunnableFuture<V> extends Runnable, Future<V> {
        void run();
    }
    分析:FutureTask除了实现了Future接口外还实现了Runnable接口,因此FutureTask也可以直接提交给Executor执行。 当然也可以调用线程直接执行(FutureTask.run())。接下来我们根据FutureTask.run()的执行时机来分析其所处的3种状态:
    (1)未启动,FutureTask.run()方法还没有被执行之前,FutureTask处于未启动状态,当创建一个FutureTask,而且没有执行FutureTask.run()方法前,这个FutureTask也处于未启动状态。
    (2)已启动,FutureTask.run()被执行的过程中,FutureTask处于已启动状态。
    (3)已完成,FutureTask.run()方法执行完正常结束,或者被取消或者抛出异常而结束,FutureTask都处于完成状态。

    下面我们再来看看FutureTask的方法执行示意图(方法和Future接口基本是一样的,这里就不过多描述了)

    分析:
    (1)当FutureTask处于未启动或已启动状态时,如果此时我们执行FutureTask.get()方法将导致调用线程阻塞;当FutureTask处于已完成状态时,执行FutureTask.get()方法将导致调用线程立即返回结果或者抛出异常。
    (2)当FutureTask处于未启动状态时,执行FutureTask.cancel()方法将导致此任务永远不会执行。
    FutureTask处于已启动状态时,执行cancel(true)方法将以中断执行此任务线程的方式来试图停止任务,如果任务取消成功,cancel(...)返回true;但如果执行cancel(false)方法将不会对正在执行的任务线程产生影响(让线程正常执行到完成),此时cancel(...)返回false。
    当任务已经完成,执行cancel(...)方法将返回false。
    最后我们给出FutureTask的两种构造函数:
    public FutureTask(Callable<V> callable) {
    }
    public FutureTask(Runnable runnable, V result) {
    }
    3.Callable<V>/Future<V>/FutureTask的使用
    通过上面的介绍,我们对Callable,Future,FutureTask都有了比较清晰的了解了,那么它们到底有什么用呢?我们前面说过通过这样的方式去创建线程的话,最大的好处就是能够返回结果,加入有这样的场景,我们现在需要计算一个数据,而这个数据的计算比较耗时,而我们后面的程序也要用到这个数据结果,那么这个时Callable岂不是最好的选择?我们可以开设一个线程去执行计算,而主线程继续做其他事,而后面需要使用到这个数据时,我们再使用Future获取不就可以了吗?下面我们就来编写一个这样的实例
    3.1 使用Callable+Future获取执行结果
    Callable实现类如下:
    package com.zejian.Executor;
    import java.util.concurrent.Callable;
    /**
     * @author zejian
     * @time 2016年3月15日 下午2:02:42
     * @decrition Callable接口实例
     */
    public class CallableDemo implements Callable<Integer> {
    	
    	private int sum;
    	@Override
    	public Integer call() throws Exception {
    		System.out.println("Callable子线程开始计算啦!");
    		Thread.sleep(2000);
    		
    		for(int i=0 ;i<5000;i++){
    			sum=sum+i;
    		}
    		System.out.println("Callable子线程计算结束!");
    		return sum;
    	}
    }
    Callable执行测试类如下:

    package com.zejian.Executor;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    /**
     * @author zejian
     * @time 2016年3月15日 下午2:05:43
     * @decrition callable执行测试类
     */
    public class CallableTest {
    	
    	public static void main(String[] args) {
    		//创建线程池
    		ExecutorService es = Executors.newSingleThreadExecutor();
    		//创建Callable对象任务
    		CallableDemo calTask=new CallableDemo();
    		//提交任务并获取执行结果
    		Future<Integer> future =es.submit(calTask);
    		//关闭线程池
    		es.shutdown();
    		try {
    			Thread.sleep(2000);
    		System.out.println("主线程在执行其他任务");
    		
    		if(future.get()!=null){
    			//输出获取到的结果
    			System.out.println("future.get()-->"+future.get());
    		}else{
    			//输出获取到的结果
    			System.out.println("future.get()未获取到结果");
    		}
    		
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		System.out.println("主线程在执行完成");
    	}
    }

    执行结果:
    Callable子线程开始计算啦!
    主线程在执行其他任务
    Callable子线程计算结束!
    future.get()-->12497500
    主线程在执行完成
    3.2 使用Callable+FutureTask获取执行结果
    package com.zejian.Executor;
    import java.util.concurrent.ExecutorService;
    import java.util.concurrent.Executors;
    import java.util.concurrent.Future;
    import java.util.concurrent.FutureTask;
    /**
     * @author zejian
     * @time 2016年3月15日 下午2:05:43
     * @decrition callable执行测试类
     */
    public class CallableTest {
    	
    	public static void main(String[] args) {
    //		//创建线程池
    //		ExecutorService es = Executors.newSingleThreadExecutor();
    //		//创建Callable对象任务
    //		CallableDemo calTask=new CallableDemo();
    //		//提交任务并获取执行结果
    //		Future<Integer> future =es.submit(calTask);
    //		//关闭线程池
    //		es.shutdown();
    		
    		//创建线程池
    		ExecutorService es = Executors.newSingleThreadExecutor();
    		//创建Callable对象任务
    		CallableDemo calTask=new CallableDemo();
    		//创建FutureTask
    		FutureTask<Integer> futureTask=new FutureTask<>(calTask);
    		//执行任务
    		es.submit(futureTask);
    		//关闭线程池
    		es.shutdown();
    		try {
    			Thread.sleep(2000);
    		System.out.println("主线程在执行其他任务");
    		
    		if(futureTask.get()!=null){
    			//输出获取到的结果
    			System.out.println("futureTask.get()-->"+futureTask.get());
    		}else{
    			//输出获取到的结果
    			System.out.println("futureTask.get()未获取到结果");
    		}
    		
    		} catch (Exception e) {
    			e.printStackTrace();
    		}
    		System.out.println("主线程在执行完成");
    	}
    }
    执行结果:
    Callable子线程开始计算啦!
    主线程在执行其他任务
    Callable子线程计算结束!
    futureTask.get()-->12497500
    主线程在执行完成

    主要参考资料:
    java并发编程的艺术

    展开全文
  • Java多线程编程

    万次阅读 2016-06-17 22:08:38
    Java多线程编程 Java多线程编程提供了内置的支持。一个多线程程序包含两个或多个能并发运行的部分。程序的每一部分都称作一 个线程,并且每个线程定义了一个独立的执行路径。 多线程是多任务的一种特别...

    Java多线程编程


    Java给多线程编程提供了内置的支持。一个多线程程序包含两个或多个能并发运行的部分。程序的每一部分都称作一

    个线程,并且每个线程定义了一个独立的执行路径。


    多线程是多任务的一种特别的形式。多线程比多任务需要更小的开销。


    这里定义和线程相关的另一个术语:进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线

    程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守候线程都结束运行后才能结束。


    多线程能满足程序员编写非常有效率的程序来达到充分利用CPU的目的,因为CPU的空闲时间能够保持在最低限度。


    一个线程的生命周


    线程经过其生命周期的各个阶段。下图显示了一个线程完整的生命周期。



    新状态: 一个新产生的线程从新状态开始了它的生命周期。它保持这个状态知道程序start这个线程。


    运行状态:当一个新状态的线程被start以后,线程就变成可运行状态,一个线程在此状态下被认为是开始执行其任务


    就绪状态:当一个线程等待另外一个线程执行一个任务的时候,该线程就进入就绪状态。当另一个线程给就绪状态的

    线程发送信号时,该线程才重新切换到运行状态。


    休眠状态: 由于一个线程的时间片用完了,该线程从运行状态进入休眠状态。当时间间隔到期或者等待的时间发生

    了,该状态的线程切换到运行状态。


    终止状态: 一个运行状态的线程完成任务或者其他终止条件发生,该线程就切换到终止状态。


    线程的优先级


    每一个Java线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。Java优先级在MIN_PRIORITY(1)和

    MAX_PRIORITY(10)之间的范围内。默认情况下,每一个线程都会分配一个优先级NORM_PRIORITY(5)。


    具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器时间。然而,线程优先级不能保证

    线程执行的顺序,而且非常依赖于平台。


    创建一个线程


    Java提供了两种创建线程方法:


    通过实现Runable接口;


    通过继承Thread类本身。


    通过实现Runnable接口来创建线程


    创建一个线程,最简单的方法是创建一个实现Runnable接口的类。


    为了实现Runnable接口,一个类只需要执行一个方法调用run(),声明如下:

    <span style="font-size:18px;">public void run()</span>

    你可以重写该方法,重要的是理解的run()可以调用其他方法,使用其他类,并声明变量,就像主线程一样。


    在创建一个实现Runnable接口的类之后,你可以在类中实例化一个线程对象。


    Thread类中定义了几个构造方法,下面的这个是我们经常使用的:

    <span style="font-size:18px;">Thread(Runnable threadOb,String threadName);</span>

    这里,threadOb 是一个实现Runnable 接口的类的实例,并且 threadName指定新线程的名字。


    新线程创建之后,你调用它的start()方法它才会运行。

    <span style="font-size:18px;">void start();</span>


    实例


    下面是一个创建线程并开始让它执行的实例:

    <span style="font-size:18px;">//创建一个新的线程
    class NewThread implements Runnable {
       Thread t;
       NewThread() {
          //创建第二个新线程
          t = new Thread(this, "Demo Thread");
          System.out.println("Child thread: " + t);
          // 开始线程
          t.start(); 
       }
    
       //第二个线程入口
       public void run() {
          try {
             for(int i = 5; i > 0; i--) {
                System.out.println("Child Thread: " + i);
                // 暂停线程
                Thread.sleep(50);
             }
         } catch (InterruptedException e) {
             System.out.println("Child interrupted.");
         }
         System.out.println("Exiting child thread.");
       }
    }
    
    public class ThreadDemo {
       public static void main(String args[]) {
          //创建一个新线程
          new NewThread(); 
          try {
             for(int i = 5; i > 0; i--) {
               System.out.println("Main Thread: " + i);
               Thread.sleep(100);
             }
          } catch (InterruptedException e) {
             System.out.println("Main thread interrupted.");
          }
          System.out.println("Main thread exiting.");
       }
    }</span>

    编译以上程序运行结果如下:



    通过继承Thread类来创建线程


    创建一个线程的第二种方法是创建一个新的类,该类继承Thread类,然后创建一个该类的实例。


    继承类必须重写run()方法,该方法是新线程的入口点。它也必须调用start()方法才能执行。


    实例


    下面是一个创建线程并开始让它执行的实例:

    <span style="font-size:18px;">// 通过继承Thread类创建线程
    class NewThread extends Thread {
       NewThread() {
          //创建第二个新线程
          super("Demo Thread");
          System.out.println("Child thread: " + this);
    	  //开始线程
          start(); 
       }
      
       //第二个线程入口
       public void run() {
          try {
             for(int i = 5; i > 0; i--) {
                System.out.println("Child Thread: " + i);
                //让线程休眠一会
                Thread.sleep(50);
             }
          } catch (InterruptedException e) {
             System.out.println("Child interrupted.");
          }
          System.out.println("Exiting child thread.");
       }
    }
      
    public class ExtendsThread {
       public static void main(String args[]) {
    	  //创建一个新线程
          new NewThread(); 
          try {
             for(int i = 5; i > 0; i--) {
                System.out.println("Main Thread: " + i);
                Thread.sleep(100);
             }
          } catch (InterruptedException e) {
             System.out.println("Main thread interrupted.");
          }
          System.out.println("Main thread exiting.");
       }
    }</span>

    编译以上程序运行结果如下:


    Thread类方法


    下表列出了Thread类的一些重要方法:



    测试线程是否处于活动状态。 上述方法是被Thread对象调用的。下面的方法是Thread类的静态方法。



    实例


    如下的ThreadClassDemo程序演示了Thread类的一些方法:

    文件名: DisplayMessage.java

    <span style="font-size:18px;">//通过实现Runnable接口创建线程
    public class DisplayMessage implements Runnable{
       private String message;
       
       public DisplayMessage(String message){
          this.message = message;
       }
       
       public void run(){
          while(true){
             System.out.println(message);
          }
       }
    }</span>

    文件名: GuessANumber.java

    <span style="font-size:18px;">//通过继承Thread类创建线程
    public class GuessANumber extends Thread{
       private int number;
       
       //构造方法
       public GuessANumber(int number){
          this.number = number;
       }
       
       public void run(){
          int counter = 0;
          int guess = 0;
    	  
          do{
              guess = (int) (Math.random() * 100 + 1);
              System.out.println(this.getName()
                           + " guesses " + guess);
              counter++;
          }while(guess != number);
    	  
          System.out.println("** Correct! " + this.getName()+ " in " + counter + " guesses.**");
       }
    }</span>

    文件名: ThreadClassDemo.java

    <span style="font-size:18px;">//测试类ThreadClassDemo
    public class ThreadClassDemo{
       public static void main(String [] args){
          Runnable hello = new DisplayMessage("Hello");
          Thread thread1 = new Thread(hello);
          thread1.setDaemon(true);
          thread1.setName("hello");
          System.out.println("Starting hello thread...");
          thread1.start();
          
          Runnable bye = new DisplayMessage("Goodbye");
          Thread thread2 = new Thread(bye);
          thread2.setPriority(Thread.MIN_PRIORITY);
          thread2.setDaemon(true);
          System.out.println("Starting goodbye thread...");
          thread2.start();
      
          System.out.println("Starting thread3...");
          Thread thread3 = new GuessANumber(27);
          thread3.start();
          try{
             thread3.join();
          }catch(InterruptedException e){
             System.out.println("Thread interrupted.");
          }
          System.out.println("Starting thread4...");
          Thread thread4 = new GuessANumber(75);
          
          thread4.start();
          System.out.println("main() is ending...");
       }
    }</span>

    运行结果如下,每一次运行的结果都不一样。


    线程的几个主要概念:


    在多线程编程时,你需要了解以下几个概念:


    线程同步


    线程间通信


    线程死锁


    线程控制:挂起、停止和恢复


    多线程的使用


    有效利用多线程的关键是理解程序是并发执行而不是串行执行的。例如:程序中有两个子系统需要并发执行,这时候

    就需要利用多线程编程。


    通过对多线程的使用,可以编写出非常高效的程序。不过请注意,如果你创建太多的线程,程序执行的效率实际上是

    降低了,而不是提升了。


    请记住,上下文的切换开销也很重要,如果你创建了太多的线程,CPU花费在上下文的切换的时间将多于执行程序的

    时间!



    展开全文
  • 本例来自《java多线程编程调试模式》: 题意:模拟流水线上的工人,  工人一直在流水线上作业,零件(可看作客户端发的请求)一到达,工人就开始进行工作,无零件时工作处于等待状态 具体的业务代码有详注释: ...

    一.本例来自《java多线程编程调试模式》:

    题意:模拟流水线上的工人,

     工人一直在流水线上作业,零件(可看作客户端发的请求)一到达,工人就开始进行工作,无零件时工作处于等待状态

    具体的业务代码有详注释:

    一测试类:
    package worker.thread.pattern;
    
    public class Main {
        public static void main(String[] args) {
        	 Channel channel = new Channel(5);   // Worker Thread数量
             channel.startWorkers();
             ClientThread alice = new ClientThread("Alice", channel);
             ClientThread bobby = new ClientThread("Bobby", channel);
             ClientThread chris = new ClientThread("Chris", channel);
             alice.start();
             bobby.start();
             chris.start();
    
             try {
                 Thread.sleep(5000);
             } catch (InterruptedException e) {
             }
             alice.stopThread();
             bobby.stopThread();
             chris.stopThread();
             channel.stopAllWorkers();
        }
    }
    

    2.客户端类:主要发送工作请求
    package worker.thread.pattern;
    
    import java.util.Random;
    
    /**
     * 不停的发送请求给工人类
     * 
     * 1.创建请求实例,并将实例发送给管理工人线程的类
     * 
     * @author lxb
     *
     */
    public class ClientThread extends Thread {
    
    	private final Channel channel;
    	private static final Random random = new Random();
    
    	private volatile boolean terminated = false; // 停止请求标志
    
    	public ClientThread(String name, Channel channel) {
    		super(name);
    		this.channel = channel;
    	}
    
    	public void run() {
    		try {
    			for (int i = 0; !terminated; i++) {
    				try {
    					Request request = new Request(getName(), i);
    					channel.putRequest(request);
    					Thread.sleep(random.nextInt(1000));
    				} catch (InterruptedException e) {
    					terminated = true;
    				}
    			}
    		} finally {
    			System.out.println(Thread.currentThread().getName()
    					+ " is terminated.");
    		}
    	}
    
    	public void stopThread() {
    		terminated = true;
    		interrupt();
    	}
    }
    

    3.请求对象:

    package worker.thread.pattern;
    
    import java.util.Random;
    
    /**
     * 请求实体类
     * @author lxb
     *
     */
    public class Request {
    
    	private final String name; //  
        private final int number;  // 
        private static final Random random = new Random();
        public Request(String name, int number) {
            this.name = name;
            this.number = number;
        }
        public void execute() {
            System.out.println(Thread.currentThread().getName() + " executes " + this);
            try {
                Thread.sleep(random.nextInt(1000));
            } catch (InterruptedException e) {
            }
        }
        public String toString() {
            return "[ Request from " + name + " No." + number + " ]";
        }
    }
    

    4.请求队列与工人线程管理类:
    package worker.thread.pattern;
    
    /**
     * 用来接受客户端线程发来的请求、将请求传递给工人线程,所以至少需要以下数据结构:
     * 1.一个队列来保存客户端发来的请求,还必须提供两个接口,一个putRequest保存请求, 另一个是取出请求takeRequest
     * 2.线程池来管理各个工人线程,这个池可以是一个线程数组,数组大小可自定义
     * 
     * @author lxb
     *
     */
    public class Channel {
    
    	private static final int MAX_REQUEST = 100; // 假设最大的请求队列值
    
    	private final Request[] requestQueue; // 保存的请求队列
    
    	private int tail;
    	private int head;
    	private int count; // 请求队列中的请求数量
    
    	private final WorkerThread[] threadPool; // 工人线程池
    
    	public Channel(int threads) {
    
    		this.requestQueue = new Request[MAX_REQUEST];
    		this.head = 0;
    		this.count = 0;
    		this.tail = 0;
    		threadPool = new WorkerThread[threads];
    
    		for (int i = 0; i < threadPool.length; i++) {
    			 threadPool[i] = new WorkerThread("Worker-" + i, this);
    		}
    	}
    	
    	/**
    	 * 开启工作线程
    	 */
    	public void startWorkers() {
    		for (int i = 0; i < threadPool.length; i++) {
    			threadPool[i].start();
    		}
    	}
    	
    	public void stopAllWorkers(){
    		for(int i=0;i<threadPool.length;i++){
    			threadPool[i].stopThread();
    		}
    	}
    
    	/**
    	 * 保存客户端发来的工作请求
    	 * 
    	 * @param request
    	 * @throws InterruptedException 
    	 */
    	public synchronized void putRequest(Request request) throws InterruptedException {
    		while (count >= requestQueue.length) {
    			wait();
    		}
    
    		requestQueue[tail] = request;
    
    		tail = (tail + 1) % requestQueue.length;
    
    		count++;
    
    		notifyAll();
    	}
    
    	public synchronized Request takeRequest() throws InterruptedException {
    		while (count <= 0) {
    			wait();
    		}
    
    		Request request = requestQueue[head];
    		head = (head + 1) % requestQueue.length;
    
    		count--;
    		notifyAll();
    		return request;
    	}
    
    }
    

    5工人线程:

    package worker.thread.pattern;
    
    /**
     * 工作线程,处理客户端发来的具体的工作请求
     * @author lxb
     *
     */
    public class WorkerThread extends Thread{
    
    	private final Channel channel;
    	private volatile boolean terminated = false;	//停止请求标志
    	
    	public WorkerThread(String name,Channel channel){
    		super(name);
    		this.channel = channel;
    	}
    	
    	public void run() {
            try {
                while (!terminated) {
                    try {                                           
                        Request request = channel.takeRequest();    
                        request.execute();                          
                    } catch (InterruptedException e) {
                        terminated = true;
                    }                                               
                }
            } finally {
                System.out.println(Thread.currentThread().getName() + " is terminated.");
            }
        }
        public void stopThread() {
            terminated = true;
            interrupt();
        }
    }
    




    展开全文
  • java多线程编程实例

    万次阅读 多人点赞 2018-05-25 10:01:22
    这篇文章主要介绍了java多线程编程实例,分享了几则多线程的实例代码,具有一定参考价值,加深多线程编程的理解还是很有帮助的,需要的朋友可以参考下。1.相关知识:Java多线程程序设计到的知识:(1)对同一个数量...
  • JAVA 多线程编程总结

    千次阅读 2012-04-05 11:08:44
    下面是Java线程系列博文的一个编目:   Java线程:概念与原理 Java线程:创建与启动 Java线程线程栈模型与线程的变量 Java线程线程状态的转换  Java线程线程的同步与锁 Java线程线程...
  • Java多线程编程总结

    千次阅读 2010-07-10 22:11:00
    Java多线程编程总结
  • 多线程面试题(值得收藏)

    万次阅读 多人点赞 2019-08-16 09:41:18
    史上最强多线程面试47题(含答案),建议收藏 金九银十快到了,即将进入找工作的高峰期,最新整理的最全多线程并发面试47题和答案总结,希望对想进BAT的同学有帮助,由于篇幅较长,建议收藏后细看~ 1、并发编程三要素?...
  • Java 多线程编程之八:多线程的调度

    万次阅读 2013-03-12 18:08:52
    本博客是“Java 多线程编程”系列的后续篇。“Java 多线程编程”系列其他博客请参阅本博客结尾部分。  有多个线程,如何控制它们执行的先后次序?  方法一:设置线程优先级。  java.lang.Thread 提供了 set...
  • Java多线程编程-(1)-线程安全和锁Synchronized概念

    万次阅读 多人点赞 2017-09-15 14:51:59
    一、进程与线程的概念 (1)在传统的操作系统中,程序并不能独立运行,作为资源分配和独立运行的基本单位都是进程。 在未配置 OS 的系统中,程序的执行方式是顺序执行,即必须在一个程序执行完后,才允许另一个...
  • Java多线程编程核心技术》推荐

    万次阅读 多人点赞 2016-03-04 21:35:43
    写这篇博客主要是给猿友们推荐一本书《Java多线程编程核心技术》。之所以要推荐它,主要因为这本书写得十分通俗易懂,以实例贯穿整本书,使得原本抽象的概念,理解起来不再抽象。只要你有一点点Java基础,你就可以...
  • 针对这样的大文件解析处理,解决方案是使用线程,分割读取指定的大文件。获取我们所需要的信息。不说,上代码了,有注释可以帮助理解。 2.代码 package com.thread.multipl.mysolution; import java.io...
  • 一、线程计数器回顾在《Java多线程编程-(6)-两种常用的线程计数器CountDownLatch和循环屏障CyclicBarrier》 这一篇中,我们使用线程计数器的方式实现了在主线程中等待计数的线程执行完之后在执行阻塞等待之后的...
  • java多线程编程技术 +代码实例

    万次阅读 2011-08-27 10:05:57
    可以指定程序包含不同的执行线程,每个线程都具有自己的方法调用堆栈和程序计数器,使得线程在与其他线程并发地执行能够共享程序范围内的资源,比如共享内存,这种能力被称为多线程编程(multithreading),在核心的C...
  • Java多线程编程-停止线程 暂停线程

    千次阅读 2017-04-05 16:16:08
    一 停止线程停止线程是在多线程开发中很重要的技术点,个人总结停止线程有下面三种方法 *

空空如也

1 2 3 4 5 ... 20
收藏数 201,072
精华内容 80,428
关键字:

多线程编程