java 关于System.out.println的多线程并发问题
来源:互联网 发布:钢结构绘图软件 编辑:程序博客网 时间:2024/05/23 19:21
如果println函数的参数为常量则不会出现线程并发问题,但是如果参数为表达式形式,则JVM在执行println函数的时候会分为几步来执行,从而造成并发问题。
所以可以看出上面程序的执行顺序为:、
张三执行完->李四执行完->王五执行完->老张只执行到加操作,被老牛打断->老牛执行完->老朱执行完->老张执行剩下的输出操作
要想有一个正常的输出顺序,应该修改代码为:
如下例子所示:
public class Test{public static void main(String[] args){ExecutorService pool = Executors.newFixedThreadPool(2);Runnable t1 = new MyRunnable("张三", 2000);Runnable t2 = new MyRunnable("李四", 3600);Runnable t3 = new MyRunnable("王五", 2700);Runnable t4 = new MyRunnable("老张", 600);Runnable t5 = new MyRunnable("老牛", 1300);Runnable t6 = new MyRunnable("老朱", 800);//执行各个线程pool.execute(t1);pool.execute(t2);pool.execute(t3);pool.execute(t4);pool.execute(t5);pool.execute(t6);//关闭线程池pool.shutdown();}}class MyRunnable implements Runnable{private static AtomicLong aLong = new AtomicLong(10000); //原子量,每个线程都可以自由操作private String name; //操作人private int data; //操作数MyRunnable(String name, int data){this.name = name;this.data = data;}public void run(){System.out.println(name + "执行了" + data + ",当前余额:" + aLong.addAndGet(data));}}
执行的结果为:
张三执行了2000,当前余额:12000
李四执行了3600,当前余额:15600
王五执行了2700,当前余额:18300
老牛执行了1300,当前余额:20200
老朱执行了800,当前余额:21000
老张执行了600,当前余额:18900
通过反编译,上面println函数的主要处理过程分为下面三步:
long l = aLong.addAndGet(data);String sb =new StringBuilder(String.valueOf(name))).append("执行了").append(data).append(",当前余额:").append(l);synchronized (this) { print(sb.toString); newLine();}
所以可以看出上面程序的执行顺序为:、
张三执行完->李四执行完->王五执行完->老张只执行到加操作,被老牛打断->老牛执行完->老朱执行完->老张执行剩下的输出操作
要想有一个正常的输出顺序,应该修改代码为:
import java.util.concurrent.ExecutorService;import java.util.concurrent.Executors;import java.util.concurrent.atomic.AtomicLong;import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class Test{public static void main(String[] args){ExecutorService pool = Executors.newFixedThreadPool(2);Lock lock = new ReentrantLock(false);Runnable t1 = new MyRunnable("张三", 2000, lock);Runnable t2 = new MyRunnable("李四", 3600, lock);Runnable t3 = new MyRunnable("王五", 2700, lock);Runnable t4 = new MyRunnable("老张", 600, lock);Runnable t5 = new MyRunnable("老牛", 1300, lock);Runnable t6 = new MyRunnable("老朱", 800, lock);//执行各个线程pool.execute(t1);pool.execute(t2);pool.execute(t3);pool.execute(t4);pool.execute(t5);pool.execute(t6);//关闭线程池pool.shutdown();}}class MyRunnable implements Runnable{private static AtomicLong aLong = new AtomicLong(10000); //原子量,每个线程都可以自由操作private String name; //操作人private int data; //操作数private Lock lock;MyRunnable(String name, int data, Lock lock){this.name = name;this.data = data;this.lock = lock;}public void run(){lock.lock();System.out.println(name + "执行了" + data + ",当前余额:" + aLong.addAndGet(data));lock.unlock();}}
结果为:
张三执行了2000,当前余额:12000
王五执行了2700,当前余额:14700
老张执行了600,当前余额:15300
老牛执行了1300,当前余额:16600
老朱执行了800,当前余额:17400
李四执行了3600,当前余额:21000
【注意】这里使用了一个对象锁,来控制对并发代码的访问。不管运行多少次,执行次序如何,最终余额均为21000,这个结果是正确的。有关原子量的用法很简单,关键是对原子量的认识,原子仅仅是保证变量操作的原子性,但整个程序还需要考虑线程安全的。
转载自:http://www.strutshome.com/index.php/archives/608 0 0
- java 关于System.out.println的多线程并发问题
- 关于System.out.println的多线程并发问题
- System.out.println 的多线程并发问题
- 关于System.out.println
- 关于 System.out.println
- java System.out.println()
- HDU 1001 java编程关于System.out.println(""); 与 System.out.print("\n");的PE错误
- 关于System.out.println和System.out.write的实验
- Java的System.out.println()的解析
- Java中System.out.println()的快捷键
- Java System.out.println()的解释
- 关于使用System.out.println()向控制台输出数据和使用out.println()向页面输出数据效率的问题
- java trick--system.out.println
- Java学习笔记——关于System.out.println()的小思考,static关键字
- Java学习笔记之关于System.out.println()的括号中的内容
- System.out.println的误解
- android的System.out.println
- System.out.println的快捷键
- ant安装与使用
- 用分布式缓存文件存储数据到本地 DistributedCache
- 小结
- HEVC-xCompressCU
- Socket心跳包机制
- java 关于System.out.println的多线程并发问题
- HEVC-初始化估计数据(帧间帧内)
- jsp from表单 get 、post 提交方式
- cocos2d-x发生undefined reference to `XX'异常 一劳永逸解决办法
- 链表操作总结
- 给自己的一封短信
- TCP/IP详解卷1:第二章(链路层)
- const 和 #define区别;
- bzoj 1718: [Usaco2006 Jan] Redundant Paths 分离的路径