关于线程安全问题

2020-08-16  本文已影响0人  bigdata张凯翔

一、 通过线程池创建A,B,C三个子线程,并设置A子线程执行1秒;B子线程执行3秒; C子线程执行7秒。
要求:①主线程等待接收子线程执行结果后再执行后续处理。② 在①的基础上,如果子线程执行时间超过5秒,则主线程不再等待子线程结果,直接执行后续流程。

import java.util.ArrayList;
import java.util.List;
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.FutureTask;
import java.util.concurrent.TimeUnit;
import java.util.concurrent.TimeoutException;

/**
 * 
 * 通过线程池创建A,B,C三个子线程,并设置A子线程执行1秒;B子线程执行3秒; C子线程执行7秒。
 * 要求:①主线程等待接收子线程执行结果后再执行后续处理。
 * ② 在①的基础上,如果子线程执行时间超过5秒,则主线程不再等待子线程结果,直接执行后续流程。
 *
 */
public class Subject2 {
    
    public static void main(String[] args) {
        // 创建三个任务
        List<FutureTask<String>> futureTasks = new ArrayList<>();
        // Task A 执行1s
        FutureTask<String> taskA = new FutureTask<String>(new Callable<String>() {

            @Override
            public String call() throws Exception {
                long start = System.currentTimeMillis();
                
                Thread.sleep(1000L);
                
                long end = System.currentTimeMillis();
                return "Task A done, 耗时:" + (end - start);
            }

        });

        futureTasks.add(taskA);

        // Task B 执行3s
        FutureTask<String> taskB = new FutureTask<String>(new Callable<String>() {

            @Override
            public String call() throws Exception {
                long start = System.currentTimeMillis();
                
                Thread.sleep(3000L);
                
                long end = System.currentTimeMillis();
                return "Task B done, 耗时:" + (end - start);
            }

        });

        futureTasks.add(taskB);

        // Task C 执行7s
        FutureTask<String> taskC = new FutureTask<String>(new Callable<String>() {

            @Override
            public String call() throws Exception {
                long start = System.currentTimeMillis();
                
                Thread.sleep(7000L);
                
                long end = System.currentTimeMillis();
                return "Task C done, 耗时:" + (end - start);
            }

        });

        futureTasks.add(taskC);

        // 创建线程池后,依次的提交任务执行
        ExecutorService executorService = Executors.newCachedThreadPool();
        for (FutureTask<String> futureTask : futureTasks) {
            executorService.submit(futureTask);
        }

        for (FutureTask<String> futureTask : futureTasks) {
            try {
                // System.out.println(futureTask.get());//依次等待所有task执行完毕
                System.out.println(futureTask.get(5, TimeUnit.SECONDS)); // 如果子线程执行时间超过5秒,则主线程不再等待子线程结果,直接执行后续流程。
            } catch (InterruptedException e) {
                System.out.println("任务执行中断...");
            } catch (ExecutionException e) {
                System.out.println("任务执行出错...");
            } catch (TimeoutException e) {
                System.out.println("任务执行超时...");
            }
        }

        executorService.shutdown();

        System.out.println("-----------所有task执行完成!------------");

        System.out.println("-----------主线程执行开始------------");

    }

}

二、 请编写程序证明ArrayList是非线程安全的。

import java.util.ArrayList;
import java.util.Collections;
import java.util.List;
import java.util.UUID;
import java.util.concurrent.CopyOnWriteArrayList;

/**
 * 
 * 请编写程序证明ArrayList是非线程安全的。
 *
 */
public class Subject2 {

    public static void main(String[] args) {
        List<String> list = new ArrayList<String>();

        //启动30个线程,同时往ArrayList添加值
        for (int i = 0; i < 30; i++) {
            new Thread(new Runnable() {
                @Override
                public void run() {
                    list.add(UUID.randomUUID().toString().substring(0, 8));
                    System.out.println(list);
                }
            }).start();
        }
        
        //上面代码执行过程,会抛出异常:java.util.ConcurrentModificationException
        
        //解决方案有很多种,核心思路就是防止ArrayList并发修改
        //解决方案1.通过Collections.synchronizedList()进行同步执行
        //List<String> list = Collections.synchronizedList(new ArrayList<String>());
        
        //解决方案2.使用CopyOnWriteArrayList代替ArrayList
        //List<String> list = new CopyOnWriteArrayList<String>();
        
        //解决方案。。。

    }

}
上一篇下一篇

猜你喜欢

热点阅读