任务(Task)
把线程比作公司员工的话,那么任务就可以被看做员工所要完成的工作内容,任务与线程并非一一对应的,通常一个线程可以用来执行多个任务。任务是一个相对的概念。一个文件可以被看作是一个任务,一个文件中的多个记录可以被看作一个任务,多个文件也可以被看作一个任务。
并发(Concurrent)
表示多个任务在同一时间段内被执行。这些任务并不是顺序执行,而往往是以交替的方式被执行。
并行(Parallel)
客户端线程(Client Thread)
从面向对象编程的角度来看,一个类总是对外提供某些服务(这也是这个类存在的意义)。其他类是通过调用该类相应的方法来使用这些类服务的。因此,一个类的方法的调用方式代码就被称为该类的客户端代码。相应的,执行客户端代码的线程就被称为客户端线程。因此客户端线程也是一个相对的概念,某个类的客户端线程随着执行该方法调用方式码的线程的变化而变化。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
32package com.blog;
public class JavaThreadCreationAndRun {
public static void main(String[] args) {
Helper helper = new Helper("Java Thread Anywhere");
Thread thread = new Thread(helper);
thread.setName("A-Worker-Thread");
thread.start();
}
static class Helper implements Runnable{
private final String message;
public Helper(String message) {
this.message = message;
}
public void doSomething(String message) {
System.out.println("do something with:"+message);
}
public void run() {
doSomething(message);
}
}
}
类Helper的doSomething方法的客户端线程就是名为A-Worker-Thread的线程
工作者线程(Worker Thread)
工作者线程是相对于客户端线程而言的。它表示客户端线程之外的用于特定用途的其他线程。
代码示例: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
52package com.blog;
import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;
public class WorkThread {
public static void main(String[] args) {
Helper helper = new Helper();
helper.init();
//此处,helper的客户端线程为main线程
helper.submit("something...");
}
static class Helper{
private final BlockingQueue<String> workQueue = new ArrayBlockingQueue<String>(100);
//用于处理队列workQueue中的任务的工作者线程
private final Thread workThread = new Thread() {
public void run() {
String task = null;
while(true) {
try {
task = workQueue.take();
} catch (InterruptedException e) {
break;
}
System.out.println(doProcess(task));
}
}
};
public void init() {
workThread.start();
}
protected String doProcess(String task) {
return task+"->processed.";
}
public void submit(String task) {
try {
workQueue.put(task);
} catch (InterruptedException e) {
Thread.currentThread().interrupt();
}
}
}
}
上下文切换(Context Switch)
多线程环境中,当一个线程的状态由RUNNABLE转换为非RUNNABLE(BLOCKED、WAITING或者TIME_WAITING)时,相应线程的上下文信息(即所谓的Context,包括CPU的寄存器和程序计数器在某一时间点的内容等)需要被保存以便相应的线程稍后再次进入RUNNABLE状态时能够在之前的执行进度的基础上继续前进。而一个线程的状态由非RUNNABLE进入RUNNABLE状态时也就可能涉及恢复之前保存的线程上下文信息并在此基础上前进。这个对线程的上下文信息进行保存和恢复的过程就被称为上下文切换。
显示锁(Explicit Lock)
指在Java代码中可以使用和控制的锁,即不是编译器和CPU内部使用的锁。包括synchronized关键字和java.util.concurrent.Lock接口的所有实现类。
线程安全(Thread Safe)
一段操作共享数据的代码能够保证在同一时间内被多个线程执行而仍然保持其正确性,就被称为是线程安全的。1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17package com.blog;
/**
* 非线程安全的计数器
* @author ming
*
*/
public class NonThreadSafeConter {
private int counter = 0;
public void increment() {
counter++;
}
public int get() {
return counter;
}
}1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21package com.blog;
/**
* 线程安全的计数器
* @author ming
*
*/
public class ThreadSafeCounter {
private int counter = 0;
public void increment() {
synchronized (this) {
counter++;
}
}
public int get() {
synchronized (this) {
return counter;
}
}
}