JAVA多线程(一)

2022-02-09 16:15:14 浏览数 (1)

进程与线程:

一个进程可以包含多个线程。多个线程可以并行,但是一个时间点只能有一个线程是运行状态。

线程的状态:

查看API可以,线程的状态分为五种:

(JVM里面的状态:These states are virtual machine states which do not reflect any operating system thread states)

1. NEW: 当新建一个Thread的时候,当前线程的处于新建状态,线程还未开始。

2. RUNNABLE: 调用Thread的start方法,线程进入可运行状态,在这个状态下,线程开始处理工作,还有一种情况是未真正处理,还正在等待操作系统的调用。

3. BLOCKED: 线程的阻塞状态。一种情况下当调用wait方法时,当前线程释放锁,其他线程获取锁,开始处理,当前线程进入阻塞状态。

4. WAITING: 不定期等待状态。等待其他线程的notify.

5. TIMED_WAITING:有一定期限的等待状态,与WAITING最明显的区别是Thread.sleep(). 可以指定sleep时间。

6. TERMINATED: 终止状态。线程处理完成。

两个JDK自带的同步工具类:CountDownLatch 和CyclicBarrier

先上代码:

代码语言:javascript复制
package com.my.thread;

import java.util.concurrent.CountDownLatch;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class CountDownLatchTest {

    static CountDownLatch latch = new CountDownLatch(1);
    
    static CountDownLatch downLatch = new CountDownLatch(10);
    
    static ExecutorService service = Executors.newCachedThreadPool();

    public static void main(String[] args) {
        final long start = System.currentTimeMillis();
        
        for (int i = 0; i < 10; i  ) {
            final int index = i 1;
                Runnable runnable = new Runnable() {
                    
                    @Override
                    public void run() {
                        
                        try {
                            latch.await();
                            long end = System.currentTimeMillis();
                            System.out.println(Thread.currentThread().getName() "===已鸣枪,第" index "位运动员出发,反应时间:" (end-start) "ms");
                            Thread.sleep((long) (Math.random() * 10000));
                            end = System.currentTimeMillis();
                            System.out.println(Thread.currentThread().getName() "===第" index "位运动员完成,用时" (end-start) "ms");
                            downLatch.countDown();
                        } catch (InterruptedException e) {
                            // TODO Auto-generated catch block
                            e.printStackTrace();
                        }
                        
                    }
                };
                service.execute(runnable);
        }
        try {
            System.out.println("鸣枪开始!");
            latch.countDown();
            
            downLatch.await();
            System.out.println("比赛结束");
            
        } catch (InterruptedException e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        service.shutdown();
    }
    
    
}

CountDownLatchTest .java

构造器中的计数值(count)实际上就是闭锁需要等待的线程数量。这个值只能被设置一次,而且CountDownLatch没有提供任何机制去重新设置这个计数值。

与CountDownLatch的第一次交互是主线程等待其他线程。主线程必须在启动其他线程后立即调用CountDownLatch.await()方法。

这样主线程的操作就会在这个方法上阻塞,直到其他线程完成各自的任务。

代码语言:javascript复制
 1 package com.my.thread;
 2 
 3 import java.util.concurrent.BrokenBarrierException;
 4 import java.util.concurrent.CyclicBarrier;
 5 import java.util.concurrent.ExecutorService;
 6 import java.util.concurrent.Executors;
 7 
 8 public class ThreadCycleBarrire {
 9     public static void main(String[] args) {
10         ExecutorService service = Executors.newCachedThreadPool();
11         final CyclicBarrier cb = new CyclicBarrier(3); // 三个线程同时到达
12         for (int i = 0; i < 3; i  ) {
13             Runnable runnable = new Runnable() {
14                 public void run() {
15                     try {
16                 //        Thread.sleep((long) (Math.random() * 10000));
17                         System.out.println(
18                                 "线程"   Thread.currentThread().getName()   "即将到达集合地点1,当前已有"   (cb.getNumberWaiting()   1)
19                                           "个已到达"   (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
20                         try {
21                             cb.await();
22                         } catch (BrokenBarrierException e) {
23                             // TODO Auto-generated catch block
24                             e.printStackTrace();
25                         }
26                         Thread.sleep((long) (Math.random() * 10000));
27                         System.out.println(
28                                 "线程"   Thread.currentThread().getName()   "即将到达集合地点2,当前已有"   (cb.getNumberWaiting()   1)
29                                           "个已到达"   (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
30                         try {
31                             cb.await();
32                         } catch (BrokenBarrierException e) {
33                             // TODO Auto-generated catch block
34                             e.printStackTrace();
35                         }
36                         Thread.sleep((long) (Math.random() * 10000));
37                         System.out.println(
38                                 "线程"   Thread.currentThread().getName()   "即将到达集合地点3,当前已有"   (cb.getNumberWaiting()   1)
39                                           "个已到达"   (cb.getNumberWaiting() == 2 ? "都到齐了,继续走啊" : "正在等候"));
40                         try {
41                             cb.await();
42                         } catch (BrokenBarrierException e) {
43                             // TODO Auto-generated catch block
44                             e.printStackTrace();
45                         }
46                     } catch (InterruptedException e) {
47                         // TODO Auto-generated catch block
48                         e.printStackTrace();
49                     }
50                 }
51             };
52             service.execute(runnable);
53         }
54         service.shutdown();
55     }
56 }

CyclicBarrier 的字面意思是可循环使用(Cyclic)的屏障(Barrier)。它要做的事情是,让一组线程到达一个屏障(也可以叫同步点)时被阻塞,直到最后一个线程到达屏障时,屏障才会开门,所有被屏障拦截的线程才会继续干活。

CyclicBarrier 可用于综合统计,用CyclicBarrier(int num,Runable run),最后运行run里面的方法。

0 人点赞