多线程、并发编程

目录

    • 多线程
      • 两个线程,一个输出字母,一个输出数字,交替输出
      • volatile
      • 线程与任务
      • 正确使用线程池
      • Executor与线程池
      • 从任务中产生返回值
      • 后台线程的finally一定会执行吗
      • 捕获异常
      • 当线程池只有一个线程的时候
      • ReentrantLock,Condition
      • BlockingQueue
      • CountDownLatch
      • Semaphore
      • Exchanger
      • ScheduledExecutorService
      • 仿真问题
        • 银行出纳员仿真
        • ReadWriteLock

多线程

两个线程,一个输出字母,一个输出数字,交替输出

方式一: LockSupport.unpark(Thread1) 与 LockSupport.park()

方式二:定义一个volatile的变r,自旋锁

方式三:两个阻塞队列capacity=1,先从队列里面取值,取到值就输出,取不到就阻塞等待

方式四:synchronize、wait、notify
注意遍历输出完之后要notify对方,否则对方会一直wait

方式五:lock.new两个condition,T1在condition1上等待,输出后通知condition2,T2在condition2上等待,输出后通知condition1

volatile

  • 只要对volatile修饰的域产生写操作,所有的读操作都会看到这个修改,因为volatile域会被立即写入主存,而读操作就发生在主存中
  • 如果多个任务同时访问某个域,那么这个域就应该是volatile的,否则就应该同步来访问
  • 一个任务的任何写入操作对这个任务来说都是可视的,所以不需要volatile

线程与任务

  • 我们对线程没有任何实际控制权
  • 将任务附着在线程上,以使得线程驱动任务

正确使用线程池

	@Bean
    public ThreadPoolTaskExecutor threadPoolTaskExecutor(){
        ThreadPoolTaskExecutor poolTaskExecutor = new ThreadPoolTaskExecutor();
        // 核心线程数
        poolTaskExecutor.setCorePoolSize(10);
        // 线程池维护线程的最大数量,只有在缓冲队列满了之后才会申请超过核心线程数的线程
        poolTaskExecutor.setMaxPoolSize(100);
        // 缓存队列
        poolTaskExecutor.setQueueCapacity(50);
        // 核心线程之外的线程在空闲时间到达之后会被销毁
        poolTaskExecutor.setKeepAliveSeconds(200);
        // 异步方法内部线程名称
        poolTaskExecutor.setThreadNamePrefix("myThread-");

        // n当然不是只有CallerRunsPolicy一种可选
        poolTaskExecutor.setRejectedExecutionHandler(new ThreadPoolExecutor.CallerRunsPolicy());
        poolTaskExecutor.initialize();
        return poolTaskExecutor;
    }
ThreadPoolExocutor 是一个executor
ThreadPoolTaskExecutor 是一个executor,还有定时调度功能
ExecutorService也是一个executor,
ScheduledExecutorService还是一个executor
newFixedThreadPool(),newCachedThreadPool() 等几个方法,
实际上也是间接调用了ThreadPoolExocutor ,不过是传的不同的构造参数

Executor与线程池

  • CachedThreadPool与FixThreadPool和SingleThreadExecutor差异
    CachedThreadPool会创建与所需数量相同的线程
    FixThreadPool会创建指定数量的线程
    SingleThreadExecutor相当于FixThreadPool参数为1
  • 任何线程池中,现有线程在可能情况下,都会被自动复用
Runnable task1 = new Runnable() {
    @Override
    public void run() {
        while (true) {
            System.out.println("111");
            try {
                TimeUnit.SECONDS.sleep(3);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
};


ExecutorService executorService = Executors.newFixedThreadPool(1);
ExecutorService executorService1 = Executors.newSingleThreadExecutor();
executorService.execute(task1);

从任务中产生返回值

class TaskWithResult implements Callable<Integer> {
    @Override
    public Integer call() throws Exception {
        return 1024;
    }
}

ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<Integer> submit = executorService.submit(new TaskWithResult());
// 阻塞直到等待结果返回
// V get(long timeout, TimeUnit unit)也可以指定等待时间
Integer integer = submit.get();
// 判断是否已经返回结果
boolean done = submit.isDone();

后台线程的finally一定会执行吗

不一定,非后台线程结束,后台线程也会结束,不会执行finally了

捕获异常

  • 你不能捕获从线程逃逸的异常
  • 异常不会从一个线程传播到另外一个线程
  • 但是使用线程池,依然会抛出异常到控制台
try {
	ExecutorService executorService = Executors.newFixedThreadPool(1);
    executorService.execute(exceptionTask);
}catch (Exception e) {
	// 捕获无效,依然会在控制台打印异常
    e.printStackTrace();
}

当线程池只有一个线程的时候

只会执行一个线程,而且会一直等这个线程执行完毕

    static class Task1 implements Runnable{
        private Object object;

        public Task1(Object object) {
            this.object = object;
        }

        @Override
        public void run() {
            synchronized (object) {
                System.out.println("task1..begin");
                try {
                    object.notifyAll();
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("task1..end");
                object.notifyAll();
            }
        }
    }

    static class Task2 implements Runnable{
        private Object object;

        public Task2(Object object) {
            this.object = object;
        }

        @Override
        public void run() {
            synchronized (object) {
                System.out.println("task2..begin");
                try {
                    object.notifyAll();
                    object.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println("task2..end");
                object.notifyAll();
            }
        }
    }

ExecutorService executorService = Executors.newFixedThreadPool(1);
executorService.execute(new Task1(lock));
executorService.execute(new Task2(lock));

ReentrantLock,Condition

ReentrantLock lock = new ReentrantLock();
lock.lock();
finally {
	lock.unlock();
}
lock.tryLock();
// 若锁被其他线程获取,等待两秒
lock.tryLock(2,TimeUnit.SECONDS);
Condition condition = lock.newCondition();
condition.signalAll();
condition.await();
// 让出锁两秒,然后继续竞争锁
condition.await(2,TimeUnit.SECONDS);

// java编程思想 704
1.一个任务是将蜡涂在汽车上,另外一个是抛光汽车,先涂蜡,再抛光,再涂蜡再抛光,重复10// java编程思想 709
2.饭店里面有1厨师和1服务员,服务员等待厨师准备好膳食,当厨师准备好,通知服务员取走膳食

BlockingQueue

  • 任何时候,都只允许一个任务插入或移除元素
  • 取元素时,若为空,阻塞等待
// java并发编程,715
1.一台机器具有三个任务,一台制作吐司,一台给吐司抹黄油,一台在抹过黄油的吐司涂果酱  

CountDownLatch

  • 设置一个初始计数值,调用await方法将阻塞,调用countDown()减少计数值,为0则放行
1.一个分析获得数据的任务,两个渲染数据到模板的任务,主线程返回静态页的任务。使用闭锁,控制最后返回静态页

2.先要分析得到数据,然后再开两个任务将数据渲染到两个模板,仅当一个模板渲染完成之后最后返回静态页

Semaphore

允许N个任务同时访问这项资源

Exchanger

用于两个任务交换对象,对象在创建的同时被消费

ScheduledExecutorService

定时任务还有quartz框架

ScheduledExecutorService scheduledExecutorService = Executors.newScheduledThreadPool(10);
// 延迟一秒启动,每隔两秒启动一次
scheduledExecutorService.scheduleAtFixedRate(new Runnable() {
    @Override
    public void run() {
        System.out.println("ScheduledTask");
    }
}, 1, 2, TimeUnit.SECONDS);

// 延迟一秒启动,执行一次
scheduledExecutorService.schedule(new Runnable() {
    @Override
    public void run() {
        System.out.println("ScheduledTask");
    }
},1, TimeUnit.SECONDS);

仿真问题

银行出纳员仿真

ReadWriteLock

你可能感兴趣的:(技术)