创建新线程
创建新线程有三种方式:
- 集成 Thread
- 实现 Runnable 接口
直接实例化Thread ```java public class MultiThreadTest { public static void main(String[] args) {
System.out.println("main thread start");Thread1 thread1 = new Thread1();thread1.start();Thread t2 = new Thread(new Runable2());t2.start();Thread t3 = new Thread(){public void run(){System.out.println(Thread.currentThread());}};t3.start();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();
}
}

