关于线程安全问题

举报
bigdata张凯翔 发表于 2021/03/29 03:57:31 2021/03/29
【摘要】 一、 通过线程池创建A,B,C三个子线程,并设置A子线程执行1秒;B子线程执行3秒; C子线程执行7秒。 要求:①主线程等待接收子线程执行结果后再执行后续处理。② 在①的基础上,如果子线程执行时间超过5秒,则主线程不再等待子线程结果,直接执行后续流程。 import java.util.ArrayList; import java.util.List; import java....

一、 通过线程池创建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>() {  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>() {  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>() {  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>(); //解决方案。。。 }

}

文章来源: www.jianshu.com,作者:百忍成金的虚竹,版权归原作者所有,如需转载,请联系作者。

原文链接:www.jianshu.com/p/8fa8bde8cac2

【版权声明】本文为华为云社区用户转载文章,如果您发现本社区中有涉嫌抄袭的内容,欢迎发送邮件进行举报,并提供相关证据,一经查实,本社区将立刻删除涉嫌侵权内容,举报邮箱: cloudbbs@huaweicloud.com
  • 点赞
  • 收藏
  • 关注作者

评论(0

0/1000
抱歉,系统识别当前为高风险访问,暂不支持该操作

全部回复

上滑加载中

设置昵称

在此一键设置昵称,即可参与社区互动!

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。

*长度不超过10个汉字或20个英文字符,设置后3个月内不可修改。