java并发编程之线程使用

java中有三种创建线程的方式:

实现 Runnable 接口;

实现 Callable 接口;

继承 Thread 类。

实现 Runnable 和 Callable 接口的类其实是可以在线程中运行的任务,最后需要通过 Thread 来调用该任务实现线程新建。

实现 Runnable 接口 需要实现 run() 方法。

通过 Thread 调用 start() 方法来启动线程。如下所示:

//线程新建与启动

public static void main(String[] args) {

TheRunnable instance = new TheRunnable();

Thread thread = new Thread(instance);

thread.start();//线程启动

}

public class TheRunnable implements Runnable {

public void run() {

// do something

}

}

Callable 接口可以有返回值,而返回值通过FutureTask 进行封装,而Runnable接口无返回值。

示例:

//启动线程并返回结果,结果为1

public static void main(String[] args) throws ExecutionException, InterruptedException {

TheCallable tc = new TheCallable();

FutureTask future = new FutureTask(tc);

Thread thread = new Thread(future);

thread.start();

}

public class TheCallable implements Callable {

public Integer call() {

return "1";

}

}

继承 Thread 类的方式,也需要实现 run() 方法,Thread 类也实现了 Runable 接口。

当程序调用 start() 方法启动一个线程时,虚拟机会将该线程放入就绪队列中等待被调度,当一个线程被调度时会执行该线程的 run() 方法。

如下所示:

public class TheThread extends Thread {

public void run() {

// do Something

}

}

public static void main(String[] args) {

TheThread tt = new TheThread();

tt.start();

}

守护进程:

使用 setDaemon() 方法将一个线程设置为守护线程。

public static void main(String[] args) {

Thread thread = new Thread(new TheRunnable());

thread.setDaemon(true);//设置守护进程

}

线程休眠:

Thread类的sleep()静态方法。Thread.sleep(millisec) 方法会休眠当前正在执行的线程,在此过程中,本线程不让出执行权或锁,millisec 单位为毫秒。

public void run() {

try {

Thread.sleep(3000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

线程让出

Thread类的静态方法yield()。

Thread.yield() ,让出当前线程的cpu所有权,让当前运行线程回到可运行状态,以允许具有相同优先级的其他线程过去运行机会,该方法只是对线程调度器的一个建议并非强制。

public void run() {

Thread.yield();

}

线程中断

interrupt()方法

它不是中断某个线程,只是给线程发送一个中断信号,让线程在无限等待时,阻塞、限期等待时能抛出InterruptedException异常从而结束线程,如果某个线程要能够中断,那么需要程序中有抛出这个异常,否则这个线程还是不会中断的。

如下示例:

private static class TheThread extends Thread {

public void run() {

try {

Thread.sleep(5000);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

会在sleep时中断并退出线程。

另外调用 interrupt() 方法会设置线程的中断标记,可以在线程代码的run()方法中调用 interrupted() 方法判断,返回 true则可以提前结束线程。

线程协同

join(): 等待线程终止。

join是Thread类的一个方法,启动线程后直接调用,即join()的作用是:“等待该线程终止再执行后面的操作”,一般是指的主线程等待子线程的终止。也就是在子线程调用了join()方法之后的代码,等到子线程结束了才能执行。

public static void main(String[] args) {

Thread th=new ThreadA("1");

th.start();

try {

th.join();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

class ThreadA extends Thread{

public void run() {

for (int i = 0; i

try {

sleep(100);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

}

运行结果:

主线程运行开始

子线程运行开始

子线程运行 : 0

子线程运行 : 1

子线程运行 : 2

子线程运行 : 3

子线程运行 : 4

子线程运行 : 5

子线程运行 : 6

子线程运行 :7

子线程运行 : 8

子线程运行 : 9

子线程运行结束

主线程运行开始

守护进程:

setDaemon(): 设置一个线程为守护线程。

守护进程:当前JVM实例中尚存在任何一个非守护线程没有结束,守护线程就全部工作;只有当JVM中最后一个用户线程结束时,守护线程才会随着JVM一同结束工作。

Daemon的作用是为其他线程的运行提供便利服务,守护线程最典型的应用就是 GC (垃圾回收器)

守护进程的子进程也是守护进程。

线程等待:

Object类的wait()方法:

让线程等待,让出本对象的锁,等待指定时间(传入超时时间参数)或无限期等待。等待指定时间后自动进入可执行状态,无限期等待则需要其他进程通知。

wait方法必须在synchronized块或方法中,执行后线程进入对象对应的等待池中。

线程通知:

notify()/notifyall(): 通知一个线程(或所有线程)继续运行。

本方法必须在synchronized块或方法中,执行后线程不会马上让出锁,而是继续执行完成。

线程状态变迁图如下:

图片摘自《Java多线程编程核心技术》

  • 发表于:
  • 原文链接https://kuaibao.qq.com/s/20200106A042H600?refer=cp_1026
  • 腾讯「云+社区」是腾讯内容开放平台帐号(企鹅号)传播渠道之一,根据《腾讯内容开放平台服务协议》转载发布内容。

扫码关注云+社区

领取腾讯云代金券

玩转腾讯云 有奖征文活动