线程生命周期,创建方式以及如何实现同步和通信

线程的生命周期

利用继承的方式创建线程并实现同步

 1 package com.vegeta;
 2 
 3 /**
 4  * 继承方式创建线程,实现同步
 5  *
 6  * @author:qxz
 7  * @create 2020-04-02 10:45
 8  */
 9 public class TestExtends {
10 
11     public static void main(String[] args) {
12         Window window1 = new Window();
13         window1.setName("窗口一");
14         Window window2 = new Window();
15         window2.setName("窗口二");
16         Window window3 = new Window();
17         window3.setName("窗口三");
18         window1.start();
19         window2.start();
20         window3.start();
21     }
22 
23 }
24 
25 class Window extends Thread {
26     private static int ticket = 100;
27 
28     @Override
29     public void run() {
30         while (true) {
31             synchronized (Window.class) {
32                 if (ticket > 0) {
33                     try {
34                         Thread.sleep(100);
35                     } catch (InterruptedException e) {
36                         e.printStackTrace();
37                     }
38                     System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket + "号票");
39                     ticket--;
40                 } else {
41                     break;
42                 }
43             }
44         }
45     }
46 }

利用实现Runnable接口创建多线程并实现同步

 1 package com.vegeta;
 2 
 3 /**
 4  * 利用实现Runnable接口方式创建多线程并实现同步
 5  *
 6  * @author:qxz
 7  * @create 2020-04-02 11:14
 8  */
 9 public class TestRunnable {
10     public static void main(String[] args) {
11         WindowRunnable windowRunnable = new WindowRunnable();
12         Thread window1 = new Thread(windowRunnable);
13         window1.setName("窗口一");
14         Thread window2 = new Thread(windowRunnable);
15         window2.setName("窗口二");
16         Thread window3 = new Thread(windowRunnable);
17         window3.setName("窗口三");
18         window1.start();
19         window2.start();
20         window3.start();
21     }
22 }
23 
24 class WindowRunnable implements Runnable{
25     private int ticket = 100;
26 
27     public void run() {
28         while (true) {
29             synchronized (this) {
30                 if (ticket > 0) {
31                     try {
32                         Thread.sleep(100);
33                     } catch (InterruptedException e) {
34                         e.printStackTrace();
35                     }
36                     System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket + "号票");
37                     ticket--;
38                 } else {
39                     break;
40                 }
41             }
42         }
43     }
44 }

实现Callable接口创建多线程,Callable接口不适合这种场景,它是带返回值的

 1 package com.vegeta;
 2 
 3 import java.util.concurrent.Callable;
 4 import java.util.concurrent.ExecutionException;
 5 import java.util.concurrent.FutureTask;
 6 
 7 /**
 8  * 实现Callable接口能获取返回值
 9  *
10  * @author:qxz
11  * @create 2020-04-02 11:32
12  */
13 public class TestCallable {
14     public static void main(String[] args) throws ExecutionException, InterruptedException {
15         WindowCallable wc = new WindowCallable();
16         FutureTask<Integer> futureTask1 = new FutureTask(wc);
17         FutureTask<Integer> futureTask2 = new FutureTask(wc);
18         FutureTask<Integer> futureTask3 = new FutureTask(wc);
19         Thread window1 = new Thread(futureTask1);
20         window1.setName("窗口一");
21         Thread window2 = new Thread(futureTask2);
22         window2.setName("窗口二");
23         Thread window3 = new Thread(futureTask3);
24         window3.setName("窗口三");
25         window1.start();
26         Integer i1 = futureTask1.get();
27         System.out.println(i1);
28         window2.start();
29         Integer i2 = futureTask2.get();
30         System.out.println(i2);
31         window3.start();
32         Integer i3 = futureTask3.get();
33         System.out.println(i3);
34 
35         System.out.println(i1 + i2 + i3);
36     }
37 }
38 
39 class WindowCallable implements Callable<Integer>{
40 
41     public Integer call() throws Exception {
42        return 1 + 2;
43     }
44 }

利用线程池实现同步

 1 package com.vegeta;
 2 
 3 import java.util.concurrent.ExecutorService;
 4 import java.util.concurrent.Executors;
 5 import java.util.concurrent.ThreadPoolExecutor;
 6 
 7 /**
 8  * 利用线程池 实现同步
 9  * 
10  * @author:qxz
11  * @create 2020-04-02 13:29
12  */
13 public class TestPool {
14     public static void main(String[] args) {
15         ExecutorService executorService = Executors.newFixedThreadPool(10);
16         ThreadPoolExecutor executor = (ThreadPoolExecutor) executorService;
17         WindowPool windowPool = new WindowPool();
18         executor.execute(windowPool);
19         executor.execute(windowPool);
20         executor.execute(windowPool);
21         executor.shutdown();
22     }
23 }
24 
25 class WindowPool implements Runnable{
26     private int ticket = 100;
27 
28     public void run() {
29         while (true) {
30             synchronized (this) {
31                 if (ticket > 0) {
32                     try {
33                         Thread.sleep(100);
34                     } catch (InterruptedException e) {
35                         e.printStackTrace();
36                     }
37                     System.out.println(Thread.currentThread().getName() + "卖出了第" + ticket + "号票");
38                     ticket--;
39                 } else {
40                     break;
41                 }
42             }
43         }
44     }
45 }

线程交互

 1 /**
 2  * 线程通信的例子:使用两个线程打印 1-100。线程1, 线程2 交替打印
 3  *
 4  * 涉及到的三个方法:
 5  * wait():一旦执行此方法,当前线程就进入阻塞状态,并释放同步监视器。
 6  * notify():一旦执行此方法,就会唤醒被wait的一个线程。如果有多个线程被wait,就唤醒优先级高的那个。
 7  * notifyAll():一旦执行此方法,就会唤醒所有被wait的线程。
 8  *
 9  * 说明:
10  * 1.wait(),notify(),notifyAll()三个方法必须使用在同步代码块或同步方法中。
11  * 2.wait(),notify(),notifyAll()三个方法的调用者必须是同步代码块或同步方法中的同步监视器。
12  *    否则,会出现IllegalMonitorStateException异常
13  * 3.wait(),notify(),notifyAll()三个方法是定义在java.lang.Object类中。
14  *
15  * 面试题:sleep() 和 wait()的异同?
16  * 1.相同点:一旦执行方法,都可以使得当前的线程进入阻塞状态。
17  * 2.不同点:1)两个方法声明的位置不同:Thread类中声明sleep() , Object类中声明wait()
18  *          2)调用的要求不同:sleep()可以在任何需要的场景下调用。 wait()必须使用在同步代码块或同步方法中
19  *          3)关于是否释放同步监视器:如果两个方法都使用在同步代码块或同步方法中,sleep()不会释放锁,wait()会释放锁。
20  *
21  * @author shkstart
22  * @create 2019-02-15 下午 4:21
23  */
24 public class CommunicationTest {
25     public static void main(String[] args) {
26         Number number = new Number();
27         Thread t1 = new Thread(number);
28         Thread t2 = new Thread(number);
29 
30         t1.setName("线程1");
31         t2.setName("线程2");
32 
33         t1.start();
34         t2.start();
35     }
36 }
37 
38 class Number implements Runnable{
39     private int number = 1;
40 
41     public void run() {
42         while(true){
43             synchronized (this) {
44                 this.notify();
45                 if(number <= 100){
46                     try {
47                         Thread.sleep(10);
48                     } catch (InterruptedException e) {
49                         e.printStackTrace();
50                     }
51                     System.out.println(Thread.currentThread().getName() + ":" + number);
52                     number++;
53                     try {
54                         //使得调用如下wait()方法的线程进入阻塞状态
55                         this.wait();
56                     } catch (InterruptedException e) {
57                         e.printStackTrace();
58                     }
59                 }else{
60                     break;
61                 }
62             }
63         }
64     }
65 }
原文地址:https://www.cnblogs.com/vegeta-xiao/p/12619737.html