• 该类实现了Runnable接口

  • 线程状态一般可分为如下几种

    创建(new),就绪(runnable),运行状态(running),阻塞(blocked),time waiting或waiting,消亡(dead)。

Thread_1

Thread_2

  • 超时等待(time waiting)状态,超过限制时间后,该线程将返回到就绪(runnable)状态。

Thread类中常用的方法:

  • start()方法

    start方法用来启动一个线程,当调用start()方法后,系统才会开启一个新的线程来执行用户定义的子任务,在这个过程中,会为相应的线程分配需要的资源。

  • run()方法

    run()方法不需要用户来调用,start方法启动一个线程之后,当该线程获得CPU执行时间时,便会自动进入run方法内去执行具体任务。Thread类必须要重写run方法(Runnable接口下的虚方法)。

  • sleep方法

1
2
sleep(long millis);		// 参数为毫秒
sleep(long millis, int nanoseconds); // 第一参数为毫秒,第二参数为纳秒

sleep让线程睡眠,交出CPU,让CPU去执行其他任务。此时该线程将处于阻塞的状态,并且在其睡眠时间内,该线程不会获得执行的机会,即使系统中已没有其他可执行线程,处于sleep中的线程也不会执行。需要注意的是,sleep方法不会释放锁,也就是说如果当前线程持有对某个对象的锁,则调用sleep方法后,其他线程将无法访问这个对象

  • yield方法

    类似于sleep方法,yield方法也是Thread类提供的一个静态方法,它可以让当前线程暂停,但它不会阻塞该线程!他只是将该线程转入到就绪态。即让当前线程暂时停一下,让系统线程调度器重新调度一次。完全可能的情况是:当某个线程调用了yield()方法暂停之后,线程调度器又将其调度出来重新执行。**另外,yield方法同样不会释放锁!**且当某个线程调用yield方法后,只有优先级与当前线程相同或者更高的就绪线程才会获取被执行的机会。

  • join方法

1
2
3
join();
join(long millis); // 参数为毫秒
join(long millis, int nanoseconds); // 第一参数为毫秒,第二参数为纳秒

主线程将等待当前线程执行完毕,或者主线程等待一端时间。

  • suspend(),resume(),stop(),即暂停,恢复,停止方法已废弃,原因是调用后线程不会释放已占用的资源(比如锁),容易引起死锁问题。

  • 线程获取synchronized锁失败,将进入同步队列,状态变为Blocked阻塞态。当其他线程释放该锁,该释放行为将唤醒阻塞在同步队列中的线程,使其重新尝试获取锁。

  • 等待/通知机制

    每个锁对象存在两种队列:等待队列,同步队列。参考“Java并发编程的艺术”图4-3.

    等待/通知方法是任意Java对象都具备的,因为这些方法被定义在所有对象的超类java.lang.Object上。

    使用wait()方法,notify()方法,notifyAll()方法时,需要先对调用对象加锁。

    notify():任意通知在同一个对象锁上等待的一个线程,使其从wait()方法返回(返回到就绪态runnable)。返回的前提有两个,一是等待线程已接收到了(或刚刚接收过了)notify()或notifyAll()信号(从等待队列转至同步队列,从wait状态转至blocked状态);二是该等待线程成功获取到了该同一对象锁(从同步队列转出,从blocked状态转至runnable状态)。

    notifyAll():通知在同一个对象锁上等待的所有线程,使某一线程从wait()方法返回(返回到就绪态runnable)。返回的前提有两个,一是等待线程已接收到了(或刚刚接收过了)notify()或notifyAll()信号(从等待队列转至同步队列,从wait状态转至blocked状态);二是该等待线程成功获取到了该同一对象锁(从同步队列转出,从blocked状态转至runnable状态)。

    注意:线程调用notify()或notifyAll()方法不会立即释放锁!该方法只是进行发送通知的行为!释放锁还是要等到synchronized代码块或synchronized方法执行完,才去释放锁。

wait()方法:调用该方法的线程进入到锁对象的等待队列,从running状态进入到wait状态,只有等待其他线程的通知或中断才会返回(返回到就绪态runnable)。注意,调用wait()方法后,会立即释放锁。

wait(long)/wait(long , int):同wait()方法,但超过规定时间后,自动从等待队列转至同步队列,从wait状态转至blocked状态。

示例代码:

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
68
69
70
import java.util.concurrent.TimeUnit;

public class ApplicationDemo {

static boolean flag = true;
static final Object lock = new Object();

static class Wait implements Runnable {
public void run() {
synchronized(lock) {
while(flag) {
try {
System.out.println(Thread.currentThread() + " flag is true. wait...");
lock.wait();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
System.out.ptintln(Thread.currentThread() + " flag is false. running...");
}
}
}

static class Notify implements Runnable {
public void run() {
synchronized(lock) {
System.out.println(Thread.currentThread() + " hold lock. notify now");
lock.notifyAll();
flag = false;
try {
TimeUnit.SECONDS.sleep(5);
} catch(InterruptedException e) {
e.printStackTrace();
}
}

// 再次加锁
synchronized(lock) {
System.out.println(Thread.currentThread() + " hold lock again.");
try {
TimeUnit.SECONDS.sleep(5);
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}

public static void main(String[] args) throw Exception {
Thread waitThread = new Thread(new Wait(), "WaitThread");
waitThread.start();
TimeUnit.SECONDS.sleep(1);
Thread notifyThread = new Thread(new Notify(), "NotifyThread");
notifyThread.start();
try {
waitThread.join();
notifyThread.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}

/*
* 返回结果:(第三行和第四行顺序可能会互换)
* Thread[WaitThread,5,main] flag is true.wait...
* Thread[NotifyThread,5,main] hold lock. notify now
* Thread[WaitThread,5,main] flag is false.running...
* Thread[NotifyThread,5,main] hold lock again.
*/

摘自/参考链接

  • 开启多线程相关代码:
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
public class ApplicationDemo {
private AtomicInteger atomicI = new AtomicInteger(0);

// 使用CAS实现线程安全计数
private void safeCount() {
for(;;) {
int i = atomicI.get();
boolean suc = atomicI.compareAndSet(i, i++);
if (suc) {
break;
}
}
}

public static void main(String[] args) {
final ApplicationDemo applicationDemo = new ApplicationDemo();
List<Thread> ts = new ArrayList<>(600);
for (int i = 0; i < 100; ++i) {
Thread t = new Thread(() -> {
for ( int j = 0; j < 1000; ++j) {
applicationDemo.safeCount();
}
});
ts.add(t);
}

for ( Thread t : ts) {
t.start();
}

for (Thread t : ts) {
try {
t.join();
} catch(InterruptedException e) {
e.printStackTrace();
}
}
}
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
public class ApplicationDemo {
public static void main(String[] args) {
new Thread(new Blocked(), "BlockedThread - 1").start();
}

static class Blocked implements Runnable {
@Override
public void run() {
synchronized(Blocked.class) {
while(true) {
System.out.println("...");
}
}
}
}
}
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
public class ApplicationDemo {
private int i = 10;
private final Object object = new Object();

class MyThread extends Thread {
@Override
public void run() {
synchronized(object) {
++i;
}
}
}

public static void main(String[] args) {
ApplicationDemo applicationDemo = new ApplicationDemo();
MyThread td_1 = application.new MyThread();
MyThread td_2 = application.new MyThread();

td_1.start();
td_2.start();

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