Java Concurrency - 线程的基础操作

Posted

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java Concurrency - 线程的基础操作相关的知识,希望对你有一定的参考价值。

创建线程

在 Java 中,创建线程有两种方式:

  • 继承 java.lang.Thread 类,重写 run 方法。
    public class MyJob extends Thread {
    
        @Override
        public void run() {
            System.out.println("Hello Thread");
        }
        
        public static void main(String[] args) {
            Thread thread = new MyJob();
            thread.start();
        }
    }
  • 实现 java.lang.Runnable 接口,然后在创建 Thread 实例时传入 Runnable 参数。
    public class MyJob implements Runnable {
        @Override
        public void run() {
            System.out.println("Hello Thread");
        }
        
        public static void main(String[] args) {
            Thread thread = new Thread(new MyJob());
            thread.start();
        }
    }

 

获取和设置线程信息

java.lang.Thread 类中的几个信息字段帮助我们来识别一个线程、观察线程的状态或是控制线程的优先级:

  • Id: 线程的 ID,每个线程拥有一个唯一的标识。
  • Name: 线程的名称。
  • Priority: 线程的优先级。优先级的范围是 1~10,值越大优先级越高。
  • State: 线程的状态。在 Java 中,线程有六种状态:NEW、RUNNABLE、BLOCKED、WAITING、TIMED_WAITING 和 TERMINATED。

上述的属性 java.lang.Thread 类都提供 getter 方法以获取线程的信息,其中 Id 和 State 是不可代码控制修改的,也不提供 setter 方法。

 

获取当前正在运行的线程

java.lang.Thread 类提供一个静态方法 currentThread(),该方法返回当前正在运行的线程。

public static void main(String[] args) {
    System.out.println(Thread.currentThread().getName());    // main
}

 

线程休眠

Thread 类的 sleep() 方法接收一个 long 参数 milliseconds,使得当前正在运行的线程休眠 milliseconds 毫秒。

TimeUnit 类同样提供提供 sleep() 方法支持线程休眠。它接收各种时间单位并将其转换成微秒。

try {
    TimeUnit.SECONDS.sleep(3);
} catch (InterruptedException e) {
    e.printStackTrace();
}

 

线程中断

有时候,我们需要在线程任务执行完毕前取消线程任务,例如当下载文件超时时取消下载任务。当 interrupt() 方法被调用时,线程的中断状态被置为 true,但是线程并不会终止。可以利用 isInterrupted 方法检测线程是否中断,并以此对线程进行控制。

public static void main(String[] args) throws Exception {
        
    Thread task = new Thread(new Runnable() {
        public void run() {
            int num = 2;
            while (!Thread.currentThread().isInterrupted()) {
                if (Primes.isPrime(num)) {
                    System.out.println(String.format("Number %d is Prime", num));
                }
                num++;
            }
        }
    });
    
    task.start();
    try {
        TimeUnit.SECONDS.sleep(3);
    } catch (InterruptedException e) {
        e.printStackTrace();
    }
    task.interrupt();
    
}

Thread 类还提供一个静态的 interrupted() 方法来判断当前正在运行的线程是否中断。但是 interrupted() 与 isInterrupted() 有些差异:isInterrupted() 方法不会修改中断状态;而 interrupted() 方法会将中断状态置为 true。 

 

join - 等待线程结束

在某些情况下,需要等待某一线程执行完毕后当前的线程才能继续执行,例如等待某个资源初始化完毕后才能执行后续的操作。 Thread 类提供了 join() 方法来实现此功能。当在线程 thread1 中调用 thread2.join() 方法,那么 thread1 线程将会挂起直至线程 thread2 结束。

Example:

public static void main(String[] args) throws Exception {
        
    Thread dataSourcesLoader = new Thread(new Runnable() {
        public void run() {
            System.out.printf("Begining data sources loading: %s\n",new Date());
            try {
                TimeUnit.SECONDS.sleep(4);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("Data sources loading has finished: %s\n",new Date());
        }
    });
    
    Thread networkConnectionsLoader = new Thread(new Runnable() {        
        @Override
        public void run() {
            System.out.printf("Begining network connections loading: %s\n",new Date());
            try {
                TimeUnit.SECONDS.sleep(6);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.printf("Network connections loading has finished: %s\n",new Date());
        }
    });
    
    dataSourcesLoader.start();
    networkConnectionsLoader.start();
    
    dataSourcesLoader.join();
    networkConnectionsLoader.join();
    System.out.printf("Main: Configuration has been loaded: %s\n",new Date());
}

jion 还有两个重载的方法:join (long milliseconds) 和 join (long milliseconds, long nanos)。第一个方法接收一个 long 参数 milliseconds,如果在线程 thread1 中调用代码 thread2.join(1000),则 thread1 线程挂起直至当 thread2 线程执行完毕;或者当 1000 毫秒过去后,即使 thread2 仍未执行完毕,thread1 依然停止挂起,继续执行。

 

守护进程

在线程启动前调用 setDaemon(true) 可以将线程设置为守护进程。

以上是关于Java Concurrency - 线程的基础操作的主要内容,如果未能解决你的问题,请参考以下文章

Java多线程和并发基础面试问答

Java 7 Concurrency Cookbook 翻译 序言

#私藏项目实操分享#Java多线程下载器基础代码

MySQL基础--11---并发线程参数 innodb_thread_concurrency

MySQL基础--11---并发线程参数 innodb_thread_concurrency

Java 7 Concurrency Cookbook 翻译 第一章 线程管理之二