引言
多线程使得程序中的多个任务可以同时执行
Java内部支持多线程
线程简介
线程 是指一个任务从头至尾的执行流程
Java中,每个任务都实现 Runnable 接口,也称为可雨欣对象
创建任务和线程
一个任务类必须实现 Runnable 接口,任务必须从线程运行。
Runnable 接口只包含一个 run 方法,创建任务类的时候实现它就行了
流程: 编写任务类
创建一个任务实例
放到线程中执行
Thread 类
Thread 类包含为任务而创建的线程的构造方法,以及控制线程的方法
void yield() 方法 为其他线程临时让出CPU时间
void sleep(long millis) 方法 可以将线程设置为休眠以确保其他线程的执行
void join() 方法 使一个线程等待另一个线程的结束
void setPriority(int p) 方法 设置线程的优先级
下面对上述两个模块举栗子:
实现任务类的两种方法:继承 Thread 类,实现 Runnable 接口 (推荐后者)
先采用继承 Thread 的方法
class NewThread extends Thread {
char c;
public NewThread(char cc) {
c = cc;
}
@Override
public void run() {
for (int i = 0; i < 10; i++)
System.out.print(c + " ");
}
}
class test {
public static void main(String[] args) {
NewThread nt1 = new NewThread('A');
NewThread nt2 = new NewThread('B');
nt1.start();
nt2.start();
new NewThread('C').start();
}
}
// 结果是
// A B B B C B A B B B B B B A C A C A C C C A A A A A C C C C
再采用实现 Runnable 接口的方法
class NewRun implements Runnable {
char c;
public NewRun(char cc) {
c = cc;
}
@Override
public void run() {
for (int i = 0; i < 10; i++)
System.out.print(c + " ");
}
}
class test {
public static void main(String[] args) {
NewRun nr1 = new NewRun('A');
Runnable nr2 = new NewRun('B');
new Thread(nr1).start();
new Thread(nr2).start();
new Thread(new NewRun('C')).start(); // 推荐这种写法
}
}
// 结果是
// A C B B B B B B C C C C C C C C C B B B B A A A A A A A A A
线程池
如果有大量并行任务,一个一个地开始可能会限制吞吐量造成性能降低。Java提供线程池的实现。
Executor 接口: 执行线程池中的任务
ExecutorService 接口: 管理和控制任务,是 Executor 的子接口
为了创建一个 Executor 对象,可以使用 Executors 类中的静态方法,比如: newFixedThreadpool(int) 方法在池中创建固定数目的线程,newCachedThreadPool() 方法会创建一个新线程,举例子看吧
将上面程序改写
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
class NewRun implements Runnable {
char c;
public NewRun(char cc) {
c = cc;
}
@Override
public void run() {
for (int i = 0; i < 10; i++)
System.out.print(c + " ");
}
}
class test {
public static void main(String[] args) {
ExecutorService executor = Executors.newFixedThreadPool(3);
executor.execute(new NewRun('A'));
executor.execute(new NewRun('B'));
executor.execute(new NewRun('C'));
executor.shutdown(); // 关闭之后不接受新任务,但是将继续执行完现有任务
}
}
// 结果是
// A C A B C C A B B C A A A C B C C C C C A A A A B B B B B B
如果用下面语句替换第20行
ExecutorService executor = Executors.newFixedThreadPool(1);
这三个任务将顺次执行,因为在线程池中只有一个线程。
如果换成 ExecutorService executor = Executors.newCachedThreadPool();
所有任务都并发执行,因为将为每个等待的任务创建一个新线程。
线程同步
线程同步用于协调相互依赖的线程的执行,如果一个共享资源被多个线程同时访问,可能会遭到破坏
不同任务以冲突的方式访问一个公共资源,称为 竞争状态。
如果没有竞争状态,则称该线程是安全的。
为了避免竞争状态,可以设置 临界区,使用关键字 synchronized 来同步。
可以在方法中添加 synchronized,比如 synchronized void count(int i){}
也可以对任何对象加锁:
synchronized(对象的引用){
}
未完待续……