顺序、并行与并发
顺序:用于表示多个操作“依次处理”。
并行:用于表示多个操作“同时处理”。
并发:用于表示“将一个操作分割成多个不笨并且允许无序处理”。
线程的启动方式
- 利用Thread类的子类(一)
创建一个类来继承java.lang.Thread类,然后该类来运行父类的start()方法。
// PrintThread类
import java.lang.Thread;
public class PrintThread extends Thread { // 继承Thread类来实现多线程
private String message;
public PrintThread(String message) {
this.message = message;
}
@Override
public void run() { // 重写run方法
for (int i = 0; i < 10000; i++) {
System.out.print(message);
}
}
}
// 主类
public class Main{
public static void main(String[] args) {
Thread t = new PrintThread("Good!") // 创建PrintThread的类的实例
t.start(); //调用start方法来创建一个新的线程
new PrintThread("Nice!").start();
}
}
知识点:Java程序的终止是指除守护线程(Daemon Thread)以外的线程全部终止。守护线程是执行后台作业的线程。我们可以通过setDaemon方法把线程设置为守护线程。
- 利用Runnable接口(二)
实际上就是建立一个类来实现Runnable接口,然后重写run()方法的方式,再通过Thread的有参构造器传入Runnable的实现类,创建一个Thread实例,通过它的start()方法来实现多线程。
// Printer类
public class Printer implements Runnable{ // 实现Runnable接口的方式
private String message;
public Printer(String message) {
this.message = message;
}
@Override
public void run() { // 重写run方法
for (int i = 0; i < 100000; i++) {
System.out.print(message);
}
}
}
// 主类
public class RunTest {
public static void main(String[] args) {
Runnable run = new Printer("Nice!"); // 创建一个Printer的实例,实现的Runnable接口
new Thread(run).start(); // 上面new的实例要作为参数传递给Thread实例,来使用start()方法来启动一个多线程
new Thread(new Printer("Good!")).start(); // 合在一起写的
}
}
补充:使用实现Runnable接口的方式的时候,new出来的该类的实例可以使用Executors.defaultThreadFactory()返回的ThreadFactory对象中,使用该对象的newThread传入Runnable接口的实现类的实例对象创建新线程,之后使用start()方法来实现多线程的启动。
// 主类
public class ThreadRun {
public static void main(String[] args) {
ThreadFactory threadFactory = Executors.defaultThreadFactory(); // 创建一个线程工厂
Thread t1 = threadFactory.newThread(new Printer("Good!")); // 使用线程工厂来创建一个线程,传入Runnable接口的实现类的实例
t1.start(); // 线程启动
threadFactory.newThread(new Printer("Nice!")).start();
}
}
- 利用实现Callable接口的方式(三)
实际上就是建立一个实现了Callable接口的类,来重写call()方法,call方法需要定义一个自己的返回值,该返回值要传给Callable的泛型中,之后在主类中实例化Callable的实现类,在通过Executors.newFixedThreadPool()方法初始化线程池,在初始化的线程池在提交几个Callable接口的实现类,去执行,执行成功之后可以通过get()方法获取返回结果,记得最后一定关闭线程池,如果不关闭,会卡在那里
// PrinterAble类
public class PrinterAble implements Callable<Boolean> { // 实现Callabe<V>接口
private String message;
public PrinterAble(String message) {
this.message = message;
}
@Override
public Boolean call() throws Exception { // 重写Call方法并且自己定义返回类型
for (int i = 0; i < 100000; i++) {
System.out.println(message);
}
return true;
}
}
// 主类
public class CallableTest {
public static void main(String[] args) {
Callable<Boolean> t1 = new PrinterAble("Nice!"); // 创建Callabe接口实现类的实例
Callable<Boolean> t2 = new PrinterAble("Good!");
ExecutorService exec = Executors.newFixedThreadPool(2); // 初始化2个线程池
Future<Boolean> t1Submit = exec.submit(t1); // 提交要运行的Callable实现类
Future<Boolean> t2Submit = exec.submit(t2);
try {
Boolean t1Result = t1Submit.get(); // 得到Callable结果
Boolean t2Result = t2Submit.get();
System.out.println("t1--------------->" + t1Result);
System.out.println("t2--------------->" + t2Result);
} catch (InterruptedException e) {
e.printStackTrace();
} catch (ExecutionException e) {
e.printStackTrace();
}
exec.shutdown(); // 关闭线程池
}
}
注:未shutdown的截图结果
注:本人是小白,PC如果搞出问题记得要长摁关机键强制关机,所以死机了的话千万别怪博主啊