java多线程 读取list--动态读取list的案例
本次介绍,我使用的是synchronized 同步代码块的关键字来读取list,在写java多线程时,一定要注意synchronized 关键字的有效范围。
ps:
如果synchronized 关键字的代码块范围太大,可能会导致 优先获取到cpu资源的第一个线程 在满足条件的情况下 一直无法跳循环,从而使得其他线程
无法给获取到被cpu调度的机会,造成:想“多线程执行代码块”的预期-》演变成了 “单线程一路走到黑 执行代码块”的惨象,也就是让多线程的预期 实际变成了单线程了。
以下 我就用1个错误的例子,和一个正确的例子给大家介绍以下吧:
1.错误的例子:实际是单线程 执行synchronized代码块的内容:
package com.cdncp.testautomation.control.conf; import java.util.ArrayList; import java.util.List; public class Test_4 { /** * 多线程处理list * * @param data 数据list * @param threadNum 线程数 */ public void handleList(List<String> data, int threadNum) { long start = System.currentTimeMillis(); for (int i = 0; i < threadNum; i++) { HandleThread thread = new HandleThread("线程[" + (i + 1) + "] ", data); thread.start(); System.out.println("thread name:" + thread.getName()); } long end = System.currentTimeMillis(); System.out.println("time:" + (end - start)); } public static void main(String[] args) { Test_4 test = new Test_4(); // 准备数据 List<String> data = new ArrayList<String>(); for (int i = 0; i < 40; i++) { data.add("item" + i); } HandleThread.info = data; test.handleList(data, 10); } }
第二个类:
package com.cdncp.testautomation.control.conf; import java.util.List; public class HandleThread extends Thread { public static List<String> info; private String threadName; private List<String> data; //静态钥匙 static Object ob = "key"; //值是任意的 public HandleThread(String threadName, List<String> data) { this.threadName = threadName; this.data = data; } @Override public void run() { while (true) { synchronized (HandleThread.class) { try { Thread.sleep(10); } catch (InterruptedException e) { e.printStackTrace(); } if (info.size() > 0) { System.out.println(this.threadName + ": " + info.toString()); info.remove(info.get(0)); } else { System.out.printf("%s:票已售空 \n", getName()); break; } } } } }
执行结果:
无法满足 按照我设定的线程数 去动态读取list(虽然读取数据是线程安全的,但是线程数不能按照预期创建的个数执行)
2.正确的例子:实现按照预定创建的 多线程 执行synchronized代码块的内容:
package com.cdncp.testautomation.control.conf; import java.util.ArrayList; import java.util.List; public class Test_4 { /** * 多线程处理list * * @param data 数据list * @param threadNum 线程数 */ public void handleList(List<String> data, int threadNum) { long start = System.currentTimeMillis(); for (int i = 0; i < threadNum; i++) { HandleThread thread = new HandleThread("线程[" + (i + 1) + "] ", data); thread.start(); System.out.println("thread name:" + thread.getName()); } long end = System.currentTimeMillis(); System.out.println("time:" + (end - start)); } public static void main(String[] args) { Test_4 test = new Test_4(); // 准备数据 List<String> data = new ArrayList<String>(); for (int i = 0; i < 40; i++) { data.add("item" + i); } HandleThread.info = data; test.handleList(data, 10); } }
第二个类:
区别就是synchronized设置的代码块范围:
ps:
我创建了9个线程,这里也是个线程去执行代码块,获取list中的数据!!!
原因分析:
如果synchronized 关键字的代码块范围太大(其实本质还是 同步代码块没写对),可能会导致 优先获取到cpu资源的第一个线程 在满足条件的情况下 一直无法跳循环,那么这个线程就一直占用cpu资源,一直执行。
synchronized 关键字的代码块的特别是:同一时间就只能有一个线程去执行,只有等这个线程执行完毕这个代码块后,资源才会被释放,然后才能让其他线程去执行这个synchronized 关键字的代码块。
案例一中,就是因为这个原因,这就从而使得其他线程(即使我创建了9个线程,其实就只要小于9个线程在执行) 无法获取到被cpu调度的机会,其他线程也就不能执行了!!!
标签:读取,list,System,线程,多线程,data,public From: https://www.cnblogs.com/pingguomang/p/18140906