一、线程
1、什么是线程
线程(thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际 运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线 程并行执行不同的任务。
2、如何创建线程
2.1、JAVA中创建线程
/**
* 继承Thread类,重写run方法
*/
class MyThread extends Thread {
@Override
public void run() {
System.out.println("myThread..." + Thread.currentThread().getName());
} }
/**
* 实现Runnable接口,实现run方法
*/
class MyRunnable implements Runnable {
@Override
public void run() {
System.out.println("MyRunnable..." + Thread.currentThread().getName());
} }
/**
* 实现Callable接口,指定返回类型,实现call方法
*/
class MyCallable implements Callable<String> {
@Override
public String call() throws Exception {
return "MyCallable..." + Thread.currentThread().getName();
} }
2.2、测试一下
public static void main(String[] args) throws Exception {
MyThread thread = new MyThread();
thread.run(); //myThread...main
thread.start(); //myThread...Thread-0
MyRunnable myRunnable = new MyRunnable();
Thread thread1 = new Thread(myRunnable);
myRunnable.run(); //MyRunnable...main
thread1.start(); //MyRunnable...Thread-1
MyCallable myCallable = new MyCallable();
FutureTask<String> futureTask = new FutureTask<>(myCallable);
Thread thread2 = new Thread(futureTask);
thread2.start();
System.out.println(myCallable.call()); //MyCallable...main
System.out.println(futureTask.get()); //MyCallable...Thread-2
}
2.3、问题
既然我们创建了线程,那为何我们直接调用方法和我们调用start()方法的结果不同?new Thread() 是否真实创建了线程?
2.4、问题分析
我们直接调用方法,可以看到是执行的主线程,而调用start()方法就是开启了新线程,那说明new Thread()并没有创建线程,而是在start()中创建了线程。
那我们看下Thread类start()方法:
class Thread implements Runnable { //Thread类实现了Runnalbe接口,实现了run()方法
private Runnable target;
public synchronized void start() {
...
boolean started = false;
try {
start0(); //可以看到,start()方法真实的调用时start0()方法
started = true;
} finally {
...
}
}
private native void start0(); //start0()是一个native方法,由JVM调用底层操作系统,开启一个线程,由操作系统过统一调度
@Override
public void run() {
if (target != null) {
target.run(); //操作系统在执行新开启的线程时,回调Runnable接口的run()方法,执行我们预设的线程任务
}
}
}
2.5、总结
-
JAVA不能直接创建线程执行任务,而是通过创建Thread对象调用操作系统开启线程,在由操作系 统回调Runnable接口的run()方法执行任务;
-
实现Runnable的方式,将线程实际要执行的回调任务单独提出来了,实现线程的启动与回调任务 解耦;
-
实现Callable的方式,通过Future模式不但将线程的启动与回调任务解耦,而且可以在执行完成后 获取到执行的结果;
二、多线程
1、什么是多线程
多线程(multithreading),是指从软件或者硬件上实现多个线程并发执行的技术。同一个线程只 能处理完一个任务在处理下一个任务,有时我们需要多个任务同时处理,这时,我们就需要创建多 个线程来同时处理任务。
2、多线程有什么好处
2.1、串行处理
public static void main(String[] args) throws Exception {
System.out.println("start...");
long start = System.currentTimeMillis();
for (int i = 0; i < 5; i++) {
Thread.sleep(2000); //每个任务执行2秒
System.out.println("task done..."); //处理执行结果
}
long end = System.currentTimeMillis();
System.out.println("end...,time = " + (end - start));
}
//执行结果
start...
task done...
task done...
task done...
task done...
task done... end...,time = 10043
2.2、并行处理
public static void main(String[] args) throws Exception {
System.out.println("start...");
long start = System.currentTimeMillis();
List<Future> list = new ArrayList<>();
for (int i = 0; i < 5; i++) {
Callable<String> callable = new Callable<String>() {
@Override
public String call() throws Exception {
Thread.sleep(2000); //每个任务执行2秒
retur