- 什么是线程:线程是一个执行路径,每个线程互相不影响
- 什么是多线程?
多线程是在一个进程中存在多个执行路径,并行执行,目的是提高执行的效率。
- 创建线程的最基本的有三种方式:
(1):extends Thread
package com.zczy.thread;
public class MyThread extends Thread{
@Override
public void run() {
for(int i=0; i<10;i++){
System.out.println("子线程打印>>>>>"+i);
}
}
public static void main(String[] args) {
System.out.println("主线程开始");
MyThread myThread = new MyThread();
myThread.start();
for(int i=0; i<10;i++){
System.out.println("主线程打印>>>>>"+i);
主线程开始
主线程打印>>>>>0
主线程打印>>>>>1
主线程打印>>>>>2
主线程打印>>>>>3
主线程打印>>>>>4
主线程打印>>>>>5
主线程打印>>>>>6
主线程打印>>>>>7
主线程打印>>>>>8
主线程打印>>>>>9
主线程结束
子线程打印>>>>>0
子线程打印>>>>>1
子线程打印>>>>>2
子线程打印>>>>>3
子线程打印>>>>>4
子线程打印>>>>>5
子线程打印>>>>>6
子线程打印>>>>>7
子线程打印>>>>>8
子线程打印>>>>>9
Process finished with exit code 0
Process finished with exit code 0
由打印的结果可以看出,它所打印的顺序不是自上而下打印的。所以主线程和子线程在运行的过程中是争抢cpu的调度,所以多线程在宏观上可以说是两个线程在同时执行,但是在微观上还是单个执行的,只不过由于cpu的调度的时间太短,我们不能识别而已。
package com.zczy.thread;
public class MyThread extends Thread{
@Override
public void run() {
for(int i=0; i<10;i++){
System.out.println("子线程打印>>>>>"+i);
}
}
public static void main(String[] args) {
System.out.println("主线程开始");
MyThread myThread = new MyThread();
// myThread.start();
//改为调用run()
myThread.run();
for(int i=0; i<10;i++){
System.out.println("主线程打印>>>>>"+i);
}
System.out.println("主线程结束");
}
}
结果:
主线程开始
子线程打印>>>>>0
子线程打印>>>>>1
子线程打印>>>>>2
子线程打印>>>>>3
子线程打印>>>>>4
子线程打印>>>>>5
子线程打印>>>>>6
子线程打印>>>>>7
子线程打印>>>>>8
子线程打印>>>>>9
主线程打印>>>>>0
主线程打印>>>>>1
主线程打印>>>>>2
主线程打印>>>>>3
主线程打印>>>>>4
主线程打印>>>>>5
主线程打印>>>>>6
主线程打印>>>>>7
主线程打印>>>>>8
主线程打印>>>>>9
主线程结束
Process finished with exit code 0
法,调用run()仅仅就是调用的方法,并没有启动一个新的线程。
(2):implents Runnable 接口
(3)实现 Callable<Object>接口
其中第三种创建线程的方式可以有返回值
package com.zczy.thread;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
public class CallableThread implements Callable<String> {
public CallableThread(){
}
@Override
public String call() throws Exception {
System.out.println("子线程---callable接口--开始睡眠5s");
Thread.sleep(5000);
String ret = "我是callable接口的返回值!";
System.out.println("子线程---callable接口--执行结束");
return ret;
}
}
package com.zczy.task;
import com.zczy.thread.CallableThread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableTask {
static ExecutorService executor = Executors.newFixedThreadPool(2);
public static void main(String[] args) throws ExecutionException, InterruptedException {
CallableThread callableThread = new CallableThread();
System.out.println("主程序开始进行");
Future<String> ret = executor.submit(callableThread);
//get 阻塞,直接拿到子线程结果
String s = ret.get();
System.out.println("从子线程得到的结果>>>>>"+s);
System.out.println("主线程睡眠5s>>>>>");
Thread.sleep(5000);
System.out.println("主程序执行结束");
}
}
结果: 主程序开始进行
子线程---callable接口--开始睡眠5s
子线程---callable接口--执行结束
从子线程得到的结果>>>>>我是callable接口的返回值!
主线程睡眠5s>>>>>
主程序执行结束
上段程序要直接得到子线程的结果,主线程才能继续运行。如果想主程序不受得到子线程结果的影响,将获得的结果放在子线程中。
package com.zczy.thread;
import java.util.HashMap;
import java.util.Map;
import java.util.concurrent.Callable;
public class CallableThread implements Callable<String> {
public CallableThread(){
}
@Override
public String call() throws Exception {
System.out.println("子线程---callable接口--开始睡眠5s");
Thread.sleep(5000);
String ret = "我是callable接口的返回值!";
System.out.println("子线程---callable接口--执行结束");
return ret;
}
}
package com.zczy.task;
import com.zczy.thread.CallableThread;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class CallableTask {
static ExecutorService executor = Executors.newFixedThreadPool(2);
String s;
public static void main(String[] args) throws Exception {
CallableThread callableThread = new CallableThread();
System.out.println("主程序开始进行");
new Thread(new Runnable() {
@Override
public void run() {
try {
Future<String> ret = executor.submit(callableThread);
//get 阻塞放到另外一个线程执行。这样主线程不会再等到结果在往下执行
String s = ret.get();
System.out.println("从子线程得到的结果>>>>>"+s);
} catch (Exception e) {
e.printStackTrace();
}
}
}).start();
System.out.println("主线程睡眠2s>>>>>");
Thread.sleep(2000);
System.out.println("主程序执行结束");
}
}