助力软件开发企业降本增效 PHP / java源码系统,只需一次付费,代码终身使用! 广告
# 创建并启动线程 ## 场景: 假如我现在需要在读数据库的同时往磁盘里写数据,这个要怎么做呢? ```java package com.thread.thread01; /** * @program: ThreadDemo * @description: 创建并启动线程 * @author: hs96.cn@Gmail.com * @create: 2020-08-26 09:56 */ public class TryConcurrency { public static void main(String[] args) { readFromDataBase(); writeDataToFile(); } /** * 读数据 */ private static void readFromDataBase() { // read data from database and handle it try { println("Begin read data from db."); Thread.sleep(1000 * 1L); println("Read data done and start handle it."); } catch (InterruptedException e) { e.printStackTrace(); } println("The data handle finish and successfully."); } /** * 写数据 */ private static void writeDataToFile() { // write data to file try { println("Begin write data to file."); Thread.sleep(1000 * 1L); println("Write data done and start handle it."); } catch (InterruptedException e) { e.printStackTrace(); } println("The data handle finish and successfully."); } private static void println(String message) { System.out.println(message); } } ``` 运行效果如下: ![](https://img.kancloud.cn/77/3b/773b064db5b5388d3b3e0c9262c341c4_1040x224.gif) 可以看到这两个方法其实是顺序执行的不是交替执行的,接下来我们打开JDK的文档,找到Thread类: ![](https://img.kancloud.cn/61/9b/619be298ecc5ad1dd3efc12308526059_1416x685.png) 可以看到在JVM启动的时候其实有一个非守护的main线程来启动我们的main函数。 为了验证这个,我们来创建一个`sleep`的线程,我们来使用`jconsole`工具来查看一下: ```java public static void main(String[] args) { try { Thread.sleep(1000 * 100L); } catch (InterruptedException e) { e.printStackTrace(); } } ``` ![](https://img.kancloud.cn/8e/14/8e14e3ddacf2dad7b25fdc850592ce8f_757x198.png) ![](https://img.kancloud.cn/89/c0/89c0fc3ddf5d92ac54f44f38ceb83eb2_300x60.png) ![](https://img.kancloud.cn/bc/6d/bc6d2c9dbad2a10273ffb0e2b93c837e_900x750.png) ![](https://img.kancloud.cn/3b/ee/3bee0c312a354684e78020438ab7b29a_900x750.png) 可以看到是有一个main线程存在的,他是waiting状态,所以,我们可以在main方法里,再创建一个线程,让这两个线程交替打印一下数字: ```java public static void main(String[] args) { Thread t1 = new Thread("Custom-Thread") { @Override public void run() { for (int i = 0; i < 1000; i++) { println("Task i=>" + i); try { Thread.sleep(1000 * 1L); } catch (InterruptedException e) { e.printStackTrace(); } } } }; t1.start(); for (int j = 0; j < 1000; j++) { try { Thread.sleep(900 * 1L); } catch (InterruptedException e) { e.printStackTrace(); } println("Task j=>" + j); } } ``` 效果如下: ![](https://img.kancloud.cn/31/b5/31b50009cd35a96ebe07c1dc6214c2b0_1040x224.gif) 可以看到这两个线程已经交替执行了。 再用`jconsole`查看一下: ![](https://img.kancloud.cn/64/00/64002fa8fab6983fd18efd7d7648cbe3_882x317.png) 把main线程的循环注释掉: ```java public static void main(String[] args) { Thread t1 = new Thread("Custom-Thread") { @Override public void run() { for (int i = 0; i < 1000; i++) { println("Task i=>" + i); try { Thread.sleep(1000 * 1L); } catch (InterruptedException e) { e.printStackTrace(); } } } }; t1.start(); /*for (int j = 0; j < 1000; j++) { try { Thread.sleep(900 * 1L); } catch (InterruptedException e) { e.printStackTrace(); } println("Task j=>" + j); }*/ } ``` 再用`jconsole`查看一下: ![](https://img.kancloud.cn/78/c1/78c1bab0db36a46b2c76b9c6bf17cd3d_869x272.png) main线程已经退出了。 还有一个容易忽略的问题: ![](https://img.kancloud.cn/f7/85/f785cabc6db12f0e469bbf9d08ff69a4_725x455.png) 显然不是,因为执行结果直接就出来了: ![](https://img.kancloud.cn/3c/a4/3ca412a501df2c0908d0f55e3a2b4081_574x115.png) 这里涉及到线程的生命周期了,后续再深入学习,这里只提一下。 现在再思考之前提出的问题:假如我现在需要在读数据库的同时往磁盘里写数据,这个要怎么做呢? ```java /** * @program: ThreadDemo * @description: 创建并启动线程 * @author: hs96.cn@Gmail.com * @create: 2020-08-26 09:56 */ public class TryConcurrency { public static void main(String[] args) { new Thread("READ-Thread") { @Override public void run() { readFromDataBase(); } }.start(); new Thread("WRITE-Thread") { @Override public void run() { writeDataToFile(); } }.start(); } /** * 读数据 */ private static void readFromDataBase() { // read data from database and handle it try { println("Begin read data from db."); Thread.sleep(1000 * 1L); println("Read data done and start handle it."); } catch (InterruptedException e) { e.printStackTrace(); } println("The data handle finish and successfully."); } /** * 写数据 */ private static void writeDataToFile() { // write data to file try { println("Begin write data to file."); Thread.sleep(1000 * 1L); println("Write data done and start handle it."); } catch (InterruptedException e) { e.printStackTrace(); } println("The data handle finish and successfully."); } private static void println(String message) { System.out.println(message); } } ``` 执行效果如下: ![](https://img.kancloud.cn/17/ec/17ec8a7953586a6d544767194d5e009b_1040x224.gif) 可以看到已经交替执行了。 再用`jconsole`查看一下: ![](https://img.kancloud.cn/8d/fa/8dfaa668cf39a003d07f3bbe290d9b1b_862x322.png) 这样我们就简单的实现了读数据库的同时往磁盘里写数据的操作。当然虽然没真正的读数据库和往磁盘里写数据,但是,主要还是理解这个交替执行的过程。