VB.net 2010 视频教程 VB.net 2010 视频教程 python基础视频教程
SQL Server 2008 视频教程 c#入门经典教程 Visual Basic从门到精通视频教程
当前位置:
首页 > temp > 简明python教程 >
  • Java 并发与多线程(2)

void put() { if (num < space)//有空位可放,可以生产 { num++; System.out.println("放入一个商品,现有" + num + "个商品," + (space - num) + "个空位"); notify();//唤醒等待该锁的线程 } else//无空位可放,等待空位 { try { System.out.println("没有空位可放,等待拿出"); wait();//进入该锁对象的等待池 } catch (InterruptedException e) { e.printStackTrace(); } } } public synchronized void take() { if (num > 0)//有商品可拿 { num--; System.out.println("拿出一个商品,现有" + num + "个商品," + (space - num) + "个空位"); notify();//唤醒等待该锁的线程 } else///等待生产产品 { try { System.out.println("没有商品可拿,等待放入"); wait();//进入该锁对象的等待池 } catch (InterruptedException e) { e.printStackTrace(); } } } }

print

没有商品可拿,等待放入
放入一个商品,现有1个商品,9个空位
放入一个商品,现有2个商品,8个空位
拿出一个商品,现有1个商品,9个空位
放入一个商品,现有2个商品,8个空位
放入一个商品,现有3个商品,7个空位
放入一个商品,现有4个商品,6个空位
拿出一个商品,现有3个商品,7个空位
放入一个商品,现有4个商品,6个空位
···

线程池

线程的启动和结束都是比较消耗时间和占用资源的,如果在系统中用到了很多的线程,大量的启动和结束动作会严重影响性能

线程池很像生产者消费者模式,消费的对象是一个一个的能够运行的任务

  1. 设计思路

    • 准备任务容器,可用 List,存放任务
    • 线程池类构造方法中创建多个执行者线程
    • 任务容器为空时,所有线程 wait
    • 当外部线程向任务容器加入任务,就会有执行者线程被 notify
    • 执行任务完毕后,没有接到新任务,就回归等待状态
  2. 实现一个线程池

    public class ThreadPool
    {
        int poolSize;// 线程池大小
        LinkedList<Runnable> tasks = new LinkedList<Runnable>();// 任务容器
        public ThreadPool(int poolSize)
        {
            this.poolSize = poolSize;
            synchronized (tasks)//启动 poolSize 个任务执行者线程
            {
                for (int i = 0; i < poolSize; i++)
                {
                    new ExecuteThread("执行者线程 " + i).start();
                }
            }
        }
        public void add(Runnable r)//添加任务
        {
            synchronized (tasks)
            {
                tasks.add(r);
                System.out.println("加入新任务");
                tasks.notifyAll();// 唤醒等待的任务执行者线程
            }
        }
        class ExecuteThread extends Thread//等待执行任务的线程
        {
            Runnable task;
            public ExecuteThread(String name)
            {
                super(name);
            }
            public void run()
            {
                System.out.println("启动:" + this.getName());
                while (true)
                {
                    synchronized (tasks)
                    {
                        while (tasks.isEmpty())
                        {
                            try
                            {
                                tasks.wait();
                            }
                            catch (InterruptedException e)
                            {
                                e.printStackTrace();
                            }
                        }
                        task = tasks.removeLast();
                        tasks.notifyAll(); // 允许添加任务的线程可以继续添加任务
                    }
                    System.out.println(this.getName() + " 接到任务");
                    task.run();//执行任务
                }
            }
        }
        public static void main(String[] args)
        {
            ThreadPool pool = new ThreadPool(3);
            for (int i = 0; i < 5; i++)
            {
                Runnable task = new Runnable()//创建任务
                {
                    public void run()//任务内容
                    {
                        System.out.println(Thread.currentThread().getName()+" 执行任务");
                    }
                };
                pool.add(task);//加入任务
                try
                {
                    Thread.sleep(1000);
                }
                catch (InterruptedException e)
                {
                    e.printStackTrace();
                }
            }
        }
    }
    

    print

    main 加入新任务
    启动:执行者线程 0
    执行者线程 0 接到任务
    执行者线程 0 执行任务
    启动:执行者线程 1
    启动:执行者线程 2
    main 加入新任务
    执行者线程 2 接到任务
    执行者线程 2 执行任务
    main 加入新任务
    执行者线程 2 接到任务
    执行者线程 2 执行任务
    
  3. java 线程池类

    • 默认线程池类 ThreadPoolExecutor 在 java.util.concurrent 包下

      ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
      /*
      第一个参数 int 类型, 10 表示这个线程池初始化了 10 个线程在里面工作
      第二个参数 int 类型, 15 表示如果 10 个线程不够用了,就会自动增加到最多 15个 线程
      第三个参数 60 结合第四个参数 TimeUnit.SECONDS,表示经过 60 秒,多出来的线程还没有接到任务,就会回收,最后保持池子里就 10 个
      第五个参数 BlockingQueue 类型,new LinkedBlockingQueue() 用来放任务的集合
      */
      
    • execute() 方法添加新任务

      public class TestThread 
      {   
          public static void main(String[] args) throws InterruptedException 
          {
              ThreadPoolExecutor threadPool= new ThreadPoolExecutor(10, 15, 60, TimeUnit.SECONDS, new LinkedBlockingQueue<Runnable>());
              threadPool.execute(new Runnable()
              {//添加任务
                  public void run() 
                  {
                      System.out.println("执行任务");
                  }    
              });
          }
      }
      
  4. java 中几种线程池

    java 线程池的顶级接口是 Executor ,子接口是 ExecutorService ,子接口使用更广泛

    Executors 类提供了一系列工厂方法用于创建线程池,返回的线程池实现了 ExecutorService 接口

    • newCachedThreadPool有缓冲的线程池,线程数 JVM 控制,有线程可使用时不会创建新线程
    • newFixedThreadPool,固定大小的线程池,任务量超过线程数时,任务存入等待队列
    • newScheduledThreadPool,创建一个线程池,可安排在给定延迟后运行命令或者定期地执行
    • newSingleThreadExecutor,只有一个线程,顺序执行多个任务,若意外终止,则会新创建一个
    ExecutorService threadPool = null;
    threadPool = Executors.newCachedThreadPool();//缓冲线程池
    threadPool = Executors.newFixedThreadPool(3);//固定大小的线程池
    threadPool = Executors.newScheduledThreadPool(2);//定时任务线程池
    threadPool = Executors.newSingleThreadExecutor();//单线程的线程池
    threadPool = new ThreadPoolExecutor(···);//默认线程池,多个可控参数
    

线程安全类

  1. StringBuffer:内部方法用 synchronized 修饰
  2. Vetort:继承于 AbstractList
  3. Stack:继承于 Vector
  4. HashTable:继承于 Dictionary,实现了 Map 接口
  5. Property:继承于 HashTable,实现了 Map 接口
  6. concurrentHashMap:分段加锁机制
作者: pgjett
出处: https://pgjett.cnblogs.com


相关教程
          
关于我们--广告服务--免责声明--本站帮助-友情链接--版权声明--联系我们       黑ICP备07002182号