线程
线程(Thread)
是操作系统运算调度的最小单位。它是独立调度和分派的基本单位,可以为操作系统内核调度的内核线程。同一进程中多条线程可以共享资源。一个进程可以有很多线程,它们可以执行不同的任务。
Java 线程的创建
1. 通过Runnable
接口创建线程
实现方法:通过重写Runnable接口中的run()
方法,继承新的实例。
// Code
class RunnableImpl implements Runnable {
@Override
public void run() {
IntStream.range(1, 4).forEach(i -> {
System.out.println(Thread.currentThread().getName() + ":" + i);
});
}
}
public class Test {
public static void main(String[] args) {
Runnable runnableImpl = new RunnableImpl();
new Thread(runnableImpl, "Thread-1").start();
new Thread(runnableImpl, "Thread-2").start();
}
}
Output
Thread-2:1
Thread-2:2
Thread-2:3
Thread-1:1
Thread-1:2
Thread-1:3
注:Thread-2
可发生在 Thread-1
前。
2. 通过继承Thread
类
实现方法: 定义Thread类的子类,重写run()
方法。通过实例的start()
方法来启动线程。
//Code
class MyTask extends Thread {
SystemTime timer = SystemTime.getInstance();
private static int MAX_NUM = 3;
@Override
public void run() {
System.out.println(timer.getTime() + Thread.currentThread().getName() + " is running");
try {
execute();
} catch (Exception e) {
e.printStackTrace();
}
}
private void execute() throws Exception {
for(int num = 1;num <= MAX_NUM;num++){
Thread.sleep(500 * num);
System.out.println(timer.getTime() + Thread.currentThread().getName() + " made " + num + (num == 1 ?" hamburger.":" hamburgers."));
}
}
}
public class Test {
public static void main(String[] args) {
MyTask myTask = new MyTask();
myTask.setName("KFC");
myTask.start();
}
}
Output
[0h 0m 0s 4ms] KFC is running
[0h 0m 0s 505ms] KFC made 1 hamburger.
[0h 0m 1s 505ms] KFC made 2 hamburgers.
[0h 0m 3s 5ms] KFC made 3 hamburgers.
3.使用Callable
和Future
创建线程
首先说一下Callable<V>
这个接口,属于java.util.concurrent
下,是一个函数式接口,方法为call()
。
@FunctionalInterface
public interface Callable<V> {
/**
* Computes a result, or throws an exception if unable to do so.
*
* @return computed result
* @throws Exception if unable to compute a result
*/
V call() throws Exception;
}
很显然,使通过特定的计算后,再返回一个结果。由于用Runnable接口的run()方法实现的线程,是无法得到线程执行结束后的结果。而我们可以通过call()来获得。
其次是Future<V>
接口
boolean cancel(boolean mayInterruptIfRunning)
中断当前执行的任务,当mayInterruptIfRunning
为 false 时,无法中断当前运行的任务。boolean isCancelled()
返回任务是否被中断。boolean isDone()
返回任务是否已完成。V get() throws InterruptedException, ExecutionException
阻塞直到返回结果。V get(long timeout, TimeUnit unit) throws InterruptedException, ExecutionException, TimeoutException
设置超时时间,返回结果。
我们使用FutureTask<V>
来模拟线程的执行,其同时实现了 Callable 和 Runnable 接口。
//Code
public class Test {
public static void main(String[] args) throws Exception {
SystemTime timer = SystemTime.getInstance();
System.out.println(timer.getTime() + "start");
Callable<ArrayList<String>> call = () -> {
ArrayList<String> messages = new ArrayList<>();
for(int num = 1;num <= 3;num ++) {
try {
Thread.sleep(500 * num);
}catch(Exception e) { }
messages.add(timer.getTime() + "KFC-" + Thread.currentThread().getName() + " sold " + num + (num == 1 ? " hamburger." : " hamburgers."));
}
return messages;
};
FutureTask<ArrayList<String>> SkySoldHam = new FutureTask<>(call);
FutureTask<ArrayList<String>> SeaSoldHam = new FutureTask<>(call);
new Thread(SkySoldHam, "Sky").start();
new Thread(SeaSoldHam, "Sea").start();
ArrayList<String> messages = SkySoldHam.get();
for(String message : messages) {
System.out.println(message);
}
messages = SeaSoldHam.get();
for(String message : messages) {
System.out.println(message);
}
System.out.println(timer.getTime() + "end!");
}
}
Output
[0h 0m 0s 0ms] start
[0h 0m 0s 559ms] KFC-Sky sold 1 hamburger.
[0h 0m 1s 559ms] KFC-Sky sold 2 hamburgers.
[0h 0m 3s 59ms] KFC-Sky sold 3 hamburgers.
[0h 0m 0s 559ms] KFC-Sea sold 1 hamburger.
[0h 0m 1s 559ms] KFC-Sea sold 2 hamburgers.
[0h 0m 3s 59ms] KFC-Sea sold 3 hamburgers.
[0h 0m 3s 60ms] end!
本文仅供学习记录之用,如有错误欢迎指正。