线程基本概念

进程与线程

  • 进程
    • 一个程序就是一个进程,经典定义是:一个执行中程序的实例。
  • 线程
    • 线程是进程执行的最小执行单元,一个进程可以包含多个线程。

什么是线程

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34

public class T01_whatisThread {


// 直接执行run方法,程序顺序执行,执行start方法,主线程与对等线程同时执行,交叉打印!
public static void main(String[] args) {

// new T1().run();
new T1().start();
for (int i = 0; i < 10; i++) {
try {
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("Main");
}
}

private static class T1 extends Thread {

@Override
public void run() {
for (int i = 0; i < 10; i++) {
try {
TimeUnit.MICROSECONDS.sleep(1);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("T1");
}
}
}
}

线程的创建方式

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66

public class T02_HowToCreateThread {


public static void main(String[] args) {

// 1.继承Thread方式
new MyThread().start();

// 2.实现Runnable接口
new Thread(new MyRun()).start();

// 3.使用匿名类
new Thread(new Runnable() {
@Override
public void run() {
System.out.println("Hello,My Anonymous");
}
}).start();

// 3.使用Lambda表达式
// new Thread(()->{
// System.out.println("Hello Lambda!");
// }).start();

// 4.实现callable接口
Thread thread = new Thread(new FutureTask<String>(new MyCall()));
thread.start();

// 5.使用线程池
ExecutorService executorService = Executors.newCachedThreadPool();
executorService.execute(new Runnable() {
@Override
public void run() {
System.out.println("Hello ThreadPool!");
}
});
executorService.shutdown();

}

private static class MyThread extends Thread {
@Override
public void run() {
System.out.println("Hello MyThread!");
}
}

private static class MyRun implements Runnable {

@Override
public void run() {
System.out.println("Hello MyRun!");
}
}


static class MyCall implements Callable<String> {

@Override
public String call() throws Exception {
System.out.println("Hello MyCall");
return "Success";
}
}
}

线程的常见方法

  • sleep
    • causes the thread to definitely stop executing for a given amount of time; if no other thread or process needs to be run, the CPU will be idle (and probably enter a power saving mode).
  • yield
    • basically means that the thread is not doing anything particularly important and if any other threads or processes need to be run, they should run. Otherwise, the current thread will continue to run.
  • join
    • The join() method of a Thread instance is used to join the start of a thread’s execution to end of other thread’s execution such that a thread does not start running until another thread ends. If join() is called on a Thread instance, the currently running thread will block until the Thread instance has finished executing.
    • join(n):It will put the current thread on wait until the thread on which it is called is dead or wait for specified time (milliseconds).

参考:Java Concurrency – yield(), sleep() and join() methods

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67

public class T03_YieldJoin {
private static class YieldThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 5; i++) {
System.out.println(Thread.currentThread().getName() + " in Control");
}
}
}


private static class JoinThread extends Thread {
@Override
public void run() {
Thread t = Thread.currentThread();
System.out.println("Current thread: " + t.getName());

// checks if current thread is alive
System.out.println("Is Alive? " + t.isAlive());
}
}


public static void main(String[] args) {
// 把当前任务放入到等待队列中,让别的线程优先执行(但有可能还是拿到当前的任务执行,比如等待队列没有任务时)
// testYield();

// 当前线程调用了别的线程,调用join()时让当前线程等待(堵塞),当调用线程执行完了,自己再执行。
testJoin();

}

private static void testJoin() {
Thread t = new Thread(new JoinThread());
t.start();

// Waits for 1000ms this thread to die.If thread is dead,execute next instruction
try {
t.join(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println("\nJoining after 1000"+
" mili seconds: \n");
System.out.println("Current thread: " +
t.getName());


// Checks if this thread is alive
System.out.println("Is alive? " + t.isAlive());

}

private static void testYield() {

Thread thread = new YieldThread();
thread.start();


for (int i = 0; i < 5; i++) {
Thread.yield();
System.out.println(Thread.currentThread().getName() + " in Control");
}
}
}

线程状态

  • 新建状态——new Thread(),对象实例化后就是新建状态了。
  • Runnable状态
    • Ready就绪状态——thread.start(),任务被扔到CPU等待队列中,等待被运行。
    • Running状态——被CPU调度器选中,开始执行,当顺利执行完后,进入Teminated结束状态,如果执行了yield(),当前线程会进入Ready就绪状态,等CPU调度器选中时,又进入Running状态。
  • Teminated结束状态——顺利执行,任务进入Teminated结束状态后,不能重新start()。
  • Bolcked阻塞 ——在执行同步代码块时没有获取锁资源,等获取锁了进入就绪状态。
  • Waiting等待——在运行状态时调用o.wait()、t.join()、LockSupport.park()进入Waiting状态,调用o.notify()、o.notifyAll()、LockSupport.unpack()又回到Running状态。
  • TimedWaiting等待——在运行状态时调用o.wait(n)、t.join(n)、Thread.sleep(n)进入TimedWaiting状态,与Waiting相似,只是按照时间等待,如果时间到了,或者线程结束则继续执行。

参考:Lifecycle and States of a Thread in Java

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42

public class T04_ThredState {

private static class MyThread extends Thread {

@Override
public void run() {
System.out.println(this.getState());
for (int i = 0; i < 10; i++) {
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(i);
}
}

}

public static void main(String[] args) {
Thread t = new MyThread();
System.out.println(t.getState());

t.start();
// 就绪状态和运行状态统称为Runnable状态
System.out.println(t.getState());

try {
t.join();
} catch (InterruptedException e) {
e.printStackTrace();
}

System.out.println(t.getState());

// 线程执行完之后,不能重新start,报IllegalThreadStateException异常,start方法中有状态校验,必须为新建状态,见源码!
// t.start();
}

}