java 创建线程的三种方法
直接使用 Thread
// 创建线程对象
Thread t = new Thread() {
public void run() {
// 要执行的任务
}
};
// 启动线程
t.start();
Runable 配合 Thread
把线程和任务分开。
Runnable runnable = new Runnable() {
public void run(){
// 要执行的任务
}
};
// 创建线程对象
Thread t = new Thread( runnable );
// 启动线程
t.start();
java8 以后,可以使用 lambda 表达式简化代码。
// 创建任务对象
Runnable task2 = () -> log.debug("hello");
// 参数1 是任务对象; 参数2 是线程名字,推荐
Thread t2 = new Thread(task2, "t2");
t2.start();
这里能够使用 lambda 的原因是:
对于只有一个抽象方法的接口,需要这种接口的对象时,就可以提供一个 lambda 表达式。这种接口称为函数式接口。
而 Runnable 就是一个函数式接口,其内部只有一个 run 方法。
FutureTask 配合 Thread
FutureTask 能够接收 Callable 类型的参数,用来处理有返回结果的情况。
// 创建任务对象
FutureTask<Integer> task3 = new FutureTask<>(() -> {
log.debug("hello");
return 100;
});
// 参数1 是任务对象; 参数2 是线程名字,推荐
new Thread(task3, "t3").start();
// 主线程阻塞,同步等待 task 执行完毕的结果
Integer result = task3.get();
log.debug("结果是:{}", result);
需要注意的是,这里调用 task3.get() 获取返回值时,子线程执行完毕之前,主线程是阻塞的。(这里的作用类似于 join 方法)
常见方法
- start():启动新线程。但 cup 的时间片不一定立刻分给它。
- run():新线程启动后自己调用的方法。如果传递了 Runnable 对象,则会调用 Runnable 中的 run 方法。
- join():等待线程运行结束。
- join(long n):最多等待 n 毫秒。
- getId:获取线程 id。
- getName():获取线程名称。
- setName():设置线程名称。
- interrupt():打断线程。如果被打断线程正在 sleep、wait、join,则会抛出异常并清除打断标记(打断标记仍为 false),否则,设置打断标记(打断标记为 true)。
- sleep(long n):静态方法,当前线程休眠 n 毫秒。此时 cpu 时间片让给其它线程。
- yield():静态方法,让出 cpu 使用权。
start 与 run
调用 run 方法时,子线程内的操作仍在 主线程执行。
调用 start 方法时,子线程内的操作才是在其它线程执行。
sleep 与 yield
sleep 方法使线程从运行态进入阻塞态,且 sleep 结束后 cpu 不一定会立刻执行该线程。
yield 方法使线程从运行态进入就绪态,主动让出 cpu。
join 方法
主要用于线程同步。
一个线程里调用另一个线程的 join 方法,就会等待 另一个线程结束才会继续执行。
interrupt 方法
打断 sleep、yield、join 状态的线程时,被打断的线程会抛出异常,并且清除打断状态。即 interrupted 参数仍为 false。
但打断正常状态的线程时,interrupted 为 true(可以用于判断是否需要料理后事)。
守护线程
在所有非守护线程都结束时,守护线程无论是否执行完,都会结束。
通过 setDaemon(true) 来设置守护线程。
标签:run,Thread,start,join,编程,并发,线程,打断,java From: https://www.cnblogs.com/huang-guosheng/p/17357438.html