多线程 - 图1

创建新线程

创建新线程有三种方式:

  1. 集成 Thread
  2. 实现 Runnable 接口
  3. 直接实例化Thread ```java public class MultiThreadTest { public static void main(String[] args) {

    1. System.out.println("main thread start");
    2. Thread1 thread1 = new Thread1();
    3. thread1.start();
    4. Thread t2 = new Thread(new Runable2());
    5. t2.start();
    6. Thread t3 = new Thread(){
    7. public void run(){
    8. System.out.println(Thread.currentThread());
    9. }
    10. };
    11. t3.start();
    12. System.out.println("main thread end");

    } }

class Thread1 extends Thread { @Override public void run() { System.out.println(Thread.currentThread()); } }

class Runable2 implements Runnable { @Override public void run() { System.out.println(Thread.currentThread()); } }

<a name="bVe5A"></a>
#   线程的状态
常见控制线程的状态有两种:

1. 线程之间的互相等待,使用 `join()` 
1. 中断线程又有两种方式
   1. 使用 `interrupt()`  和 `isInterrupted()` 
   1. 使用共享变量的 flag
<a name="r0hor"></a>
## 等待
```java
public class MultiThreadStatusTest {
    public static void main(String[] args) throws InterruptedException {
        // 线程的相互等待
        System.out.println("Main Thread start " + Thread.currentThread());
        Thread t1 = new Thread(){
            @Override
            public void run() {
                System.out.println("Sub Thread start " + Thread.currentThread());
            }
        };
        Thread t2 = new Thread(){
            @Override
            public void run() {
                System.out.println("Sub Thread start " + Thread.currentThread());
            }
        };

        t1.start();
        t2.start();
        t1.join();
        t2.join();

        System.out.println("Main Thread end");
        /**
         * 
         * Main Thread start Thread[main,5,main]
         * Sub Thread start Thread[Thread-0,5,main]
         * Sub Thread start Thread[Thread-1,5,main]
         * Main Thread end
         * 
         * */
    }
}

中断

普通的中断,只要发出 interrupt, 在线程中对于 interrupt 进行合适的处理。
逻辑
启动线程 t -> 主线程阻塞住,不继续走 -> 主线程唤醒,执行 interruput -> 发出中断请求给线程 t -> 线程 t 开始处理中断请求的内容 -> 主线程等待线程 t 返回信号 -> 结束主线程

public class MultiThreadInterruptTest {
    public static void main(String[] args) throws InterruptedException {
        MyThreadForInterrupt t = new MyThreadForInterrupt();
        t.start();
        Thread.sleep(1000);
        t.interrupt();
        t.join();
        System.out.println("Main thread end");
    }
}

class MyThreadForInterrupt extends Thread {
    @Override
    public void run() {
        int n = 0;
        while(! interrupted()){
            n ++ ;
            System.out.println(n);
        }
    }
}

另外一种方式,是通过共享变量来中断多线程

public class MultiThreadInterruputTest3 {
    public static void main(String[] args) throws InterruptedException {
        Hello3 h3 = new Hello3();
        h3.start();

        Thread.sleep(1000);
        h3.flag = false;

        System.out.println("Main Thread end");


    }
}

class Hello3 extends Thread {
    public volatile boolean flag = true;
    @Override
    public void run() {
        int n = 0;
        while(flag) {
            n ++;
            System.out.println(Thread.currentThread() + " : " +String.valueOf(n));
        }
    }
}

守护线程

JVM启动 main线程,main线程又可以启动其他线程。当所有线程都运行结束时,JVM退出,进程结束。
但有一种线程叫做守护线程,它是为了其他线程服务的。只要当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当最后一个非守护线程结束时,守护线程随着JVM一同结束工作

import java.time.LocalTime;

public class MultiThreadSetDaem {
    public static void main(String[] args) throws InterruptedException {
        DaemThread t = new DaemThread();
        t.setDaemon(true);
        t.start();
        Thread.sleep(10000);
        System.out.println("Main thread stop");
    }
}

class DaemThread extends Thread {
    @Override
    public void run() {
        while(true){
            System.out.println(LocalTime.now());
            try{
                Thread.sleep(1000);
            }catch (InterruptedException e){
                System.out.println("interrupted");
            }
        }

    }
}

同步方法

针对的是非原子操作,比如 n = n + 1 ,这是一个非原子操作,是一个过程,假设 n = 0 , 线程 A 正要执行 n = n + 1 , 这个时候,线程B 横空出世,直接先执行了 n = n + 1 = 1 , 那么线程 A 就会变成 n = 1+1 = 2. 同步方法,可以保证你进来使用这个方法的时候,不会出现其他线程来修改你的值,但是还需要注意线程的逻辑。并非这么做,就可以得到想要的结果。

class Counter{
    public static int count = 0;
    public synchronized void add(int i) throws InterruptedException {
        System.out.println(count + " + " + i + " " + new Date());
        Thread.sleep((long) Math.floor(Math.random()*1000));
        count += i;
    }
    public  synchronized  void del(int i) throws InterruptedException {
        System.out.println(count + " - " + i + " " + new Date());
        Thread.sleep((long) Math.floor(Math.random()*1000));
        count -= i;

    }

    public int getCount() {
        System.out.println("Result: " + count);
        return count;
    }
}

public class SynchroinzedTest {
    public static void main(String[] args) throws InterruptedException {
        Counter c1 = new Counter();
        Counter c2 = new Counter();

        Thread t2 = new Thread(){
            public void run(){
                try {
                    c1.del(22);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        };

        Thread t = new Thread(){
            public void run(){
                try {
                    c2.add(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            };
        };
        t2.start();
        t2.join();
        t.start();
        t.join();
        c2.getCount();
    }
}

wait and notify