本文共 2483 字,大约阅读时间需要 8 分钟。
深入理解java虚拟机中有这样一段代码
package AtomicTest;import java.util.concurrent.atomic.AtomicInteger;public class AtomicTest { public static AtomicInteger race = new AtomicInteger(0); public static void increase() { race.incrementAndGet(); } public static final int THREADS_COUNT = 5; public static void main(String[] args) throws Exception { Thread[] threads = new Thread[THREADS_COUNT]; for(int i = 0; i < THREADS_COUNT; i++) { threads[i] = new Thread(new Runnable() { @Override public void run() { for(int i = 0; i < 10000; i++) { increase(); } } }); threads[i].start(); } while(Thread.activeCount() > 1) { Thread.yield(); } System.out.println(race); }}
这段代码放到IDEA中会陷入死循环、为什么呢?因为在IDEA中有一个Monitor Ctrl-Break的线程来监听中断程序执行的信号、
改为 > 2就可以了。
可以使用Thread.enumerate()来打印出有哪些线程
Thread[] threads1 = new Thread[10]; int threadNum = Thread.enumerate(threads1); for(int i = 0; i < threadNum; i++) { System.out.println(threads1[i].getName()); }
但是我觉得使用join()更好。
但是join()不能乱用, 不能把join()放在创建线程的循环体内, 因为在执行join()的那一刻, 主线程会立即等待该线程执行完再继续执行下面的代码,
for(int i = 0; i < THREADS_COUNT; i++) { threads[i] = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(10000); }catch (InterruptedException e) { e.printStackTrace(); } } }); threads[i].start(); threads[i].join(); System.out.println("hello"); }
也就是如果按上面所写, 就是先开一个线程, 然后主线程等待该线程结束,打印hello, 然后再开一个线程, 主线程等待第二个线程结束, 再打印hello, 这样就变成串行执行了。完全没有并发的优势。为了验证这一点,我把线程任务设置为睡眠10s, 其执行结果就是每10s打印一次hello...
正确的写法:
for(int i = 0; i < THREADS_COUNT; i++) { threads[i] = new Thread(new Runnable() { @Override public void run() { try { Thread.sleep(2000); }catch (InterruptedException e) { e.printStackTrace(); } } }); threads[i].start(); System.out.println("hello"); } for(int i = 0; i < THREADS_COUNT; i++) { threads[i].join(); }
这样就会在2s时, 同时print 10个hello, 而不是每隔2s打印一个hello。
转载地址:http://hnzji.baihongyu.com/