soa---java 多线程的---线程池

       现在soa 与分布式计算已经成为互联网公司技术的标配

       那他包含的知识点应该熟悉了解,并以此为基础,去应用,调优各种soa的框架。

       包含如下的四点,是分布式的基础。

        a java 多线程 承接高吞吐量。

        b java nio 承接高并发,与交互协议的定制。

        c java 反射  完成序列化与反序列化。

        d 设计模式的应用 保证应用的扩展性。


大家都知道,多线程工作的好处---->提高机器的资源的利用率,提高的业务的处理效率。模拟现实生活团队工作,便于业务建模。

那java应用程序中对于线程执行业务有哪几种方式?
    1  串行的执行业务线程 (缺点--->低响应 + 低吞吐)
    2  无止境的创建线程执行 (资源管理性差,高负载下,崩的命)
    3  利用有界队列+一组多线程  (生产者 与 消费者模式)执行 
       有个图 从   Wikipedia 扒下来的
         soa---java 多线程的---线程池_第1张图片
 大家可以看看。task queue里面的一饼 是等完成业务类。Completed Tasks 里面是完成了的。
                         thread pool 绿色的一饼,表示正在执行的业务(同一水平线上,那么多饼,表示并行。)

以前都直接使用threadGroup 进行一组线程的管理,也就是创建线程池。现在都用这个Executor jdk提供的NB框架创建线程池。
为了了解并发包里面的线程池的设置,自己先整一个稍微能用的线程池,了解一下生产者与消费者模式。
对于线程池的设计,我了解了如下几个方面。
  •      怎么进行池的设计?----thread group 进行管理
  •      怎么 初始化池子里面的线程? ------这里设置了一个基准数。在线程池启动的时候就直接全部加上。
  •       怎么停止线程里面的线程? ----thread group 进行管理。(threadGroup里面有一个interrput()方法)
  •      怎么对于确定池里面的线程的工作内容? 工作线程~!可以用命令模式。用队列保存相应的请求的任务。
  •      线程空闲了怎么放回到池子里面?线程创建,在线程池,销毁前就不能 在TERMINATED状态,不然就失去了线程池的最大功效。工作线程里面不断的轮询的调用队列里面的pop方法,没有的时候,就wait了。对于队列添加的时候,就进行notify() 注意不是notifyAll().
 
这里有一个例子是csdn上的,我这边再拿过来说明下。
代码如下:
package threadPractice.threadpool;

import java.util.LinkedList;
import java.util.List;


/**
 * 因为要了解Thread 里面各种协调机制,这里就不用并发包里面的协调机制了。
 * @author 486636
 *
 */
public class ThreadPoolManager extends ThreadGroup{

	/**
	 * 线程池大小
	 */
	private int threadSize=3;
	/**线程池是否开启标识
	 * */
	private int flagThreadPoolValid;
	
	public ThreadPoolManager(String name) {
		super(name);
		//设置些 ThreadGroup 的子类 ThreadPoolManager 为守护线程group
		setDaemon(true);
	}
    /**
     * 没有用线程安全的,只能放monitor 监视了。这里注意用了LinkedList 它是可以自动扩展的。简化了开发。
     */
	List<Task> taskList= new LinkedList<Task>();
	
	
	
	
	
	/**
     * @brief 开启线程池
     * @param null
     * @return void
     */
    public synchronized void threadPoolStart(){

        if(threadSize ==0 || flagThreadPoolValid !=0){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return ;
        }

        if( taskList ==null ){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;
        }
        
     // 创建并开启线程例程
        for (int i = 0;i<threadSize;i++){

             new WorkThread(i).start();

        }

        flagThreadPoolValid = 1;

}
    
    
    /**
     * @brief 关闭线程池
     * @param null
     * @return void
     */
    public synchronized void threadPoolEnd(){

        if(threadSize ==0 || flagThreadPoolValid !=1){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;

        }
        if(taskList ==null ){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;
        }

        taskList.clear();
        threadSize = 0;
        flagThreadPoolValid = 0;

        // 继承自父类,中断ThreadGroup中添加的所有线程
        interrupt();

    }
    
    
    /**
     * @brief 向线程池管理类的任务队列中添加任务
     * @param newTask Task任务类
     * @return void
     */
    public synchronized void addTask(Task newTask){

        if(taskList == null ){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return;
        }

        taskList.add(newTask);

        //唤醒一个正在getTask()方法中等待任务的工作线程 用notify 的条件。
        //1 在监视器里面等待的线程只有一种类型的统一线程。
        //2 生产一个,最多能让一个来消费。
        notify();

    }

    
    
    /**
     * @brief 获取线程池中任务队列中的任务,这里包含了如何停止线程,请详细查看说明
     * @param null
     * @return Task类
     */
    public synchronized Task getTask(){

        if(taskList ==null ){

            try {
                throw new Exception();
            } catch (Exception e) {
                e.printStackTrace();
            }

            return null;
        }
        /**  为什么要用while wait() api 里面说得清清楚楚
		          正如具有一个参数的函数版本,
		          由于wait()函数调用过程中可能发生中断、虚假唤醒,
		          因此这个方法必须在检测循环中使用。
		          另外,在这里,如果不使用while循环,存在如下一种问题:
		          抛出地址越界异常。
		          例如:
		          主线程添加了一个任务,这样会唤醒一个线程。在这个线程被唤醒执行。
		          此时主线程添加另外一个任务,又唤醒一个线程。
		          第一个线程其抓取任务后,继续抓取下一个任务执行,也就是抓取添加的第二个任务。
		          这样队列中已经不存在任务。第二个被唤醒的线程必然在执行remove(0)的时候抛出上述异常。
		          而且也不能仅仅是if判断,因为唤醒获取锁后,
		          会直接执行wait()后的代码,只有while可以达到进行判断的目的。
        */
        while(taskList.size() == 0 ){ 

            try {
                wait();
            } catch (InterruptedException e) {//被终断了,应该立即返回。在thread.interrupt()里面有两个while 循环,getTask 里面的while循环。
            	                              //还有一个是WorkThread里面的while循环.   WorkThread 里面的while循环 跳出有两点,一点就是task为空,一点就是线程被打断
                e.printStackTrace();
                Thread.currentThread().interrupt(); 
                                             //thread 在wait()时,如果被打断了,就会抛出InterruptedException ,并将interrupted status重置。请了解。(wait() api,interrupte() api 里面说得很清楚)
                return null;
            }

        }

        return  taskList.remove(0);

    }
    
    /**
     * @brief 内部类,工作线程类
     */
    private class WorkThread extends Thread{

        public WorkThread(int threadID) {

            //父类构造方法,将线程加入到ThreadGroup中
            super(ThreadPoolManager.this,""+threadID);
        }

        /**
          * @brief 重写父类Thread的run方法
          * @param null
          * @return void
          */
        public void run(){

            //isInterrupted()方法继承自Thread类,判断线程是否被中断
            while(! isInterrupted()){

                Task runTask = getTask();

                //getTask()返回null或者线程执行getTask()时被中断
                if(runTask == null)    break ;

                runTask.run();

            }

        }

    }
    
    
    
}



上面有详细的解释,这里重要提一下,1 什么时候用notify,什么时候用notifyall .
          2 怎么停止线程组里面的线程,threadGroup.
          3 生产者-消费者 模式的理解------->其实就是命令模式。


接下来详细说一下 上面这个例子,用uml 图表示
先上uml图
状态图
  
soa---java 多线程的---线程池_第2张图片
时序图 getTask

soa---java 多线程的---线程池_第3张图片
时序图addTask

soa---java 多线程的---线程池_第4张图片


对于其他方法的


soa---java 多线程的---线程池_第5张图片

相关代码链接

threadGroup线程池


你可能感兴趣的:(soa---java 多线程的---线程池)