# 創建并啟動線程
## 場景:
假如我現在需要在讀數據庫的同時往磁盤里寫數據,這個要怎么做呢?
```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);
}
}
```
運行效果如下:

可以看到這兩個方法其實是順序執行的不是交替執行的,接下來我們打開JDK的文檔,找到Thread類:

可以看到在JVM啟動的時候其實有一個非守護的main線程來啟動我們的main函數。
為了驗證這個,我們來創建一個`sleep`的線程,我們來使用`jconsole`工具來查看一下:
```java
public static void main(String[] args) {
try {
Thread.sleep(1000 * 100L);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
```




可以看到是有一個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);
}
}
```
效果如下:

可以看到這兩個線程已經交替執行了。
再用`jconsole`查看一下:

把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`查看一下:

main線程已經退出了。
還有一個容易忽略的問題:

顯然不是,因為執行結果直接就出來了:

這里涉及到線程的生命周期了,后續再深入學習,這里只提一下。
現在再思考之前提出的問題:假如我現在需要在讀數據庫的同時往磁盤里寫數據,這個要怎么做呢?
```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);
}
}
```
執行效果如下:

可以看到已經交替執行了。
再用`jconsole`查看一下:

這樣我們就簡單的實現了讀數據庫的同時往磁盤里寫數據的操作。當然雖然沒真正的讀數據庫和往磁盤里寫數據,但是,主要還是理解這個交替執行的過程。
- 微服務
- 服務器相關
- 操作系統
- 極客時間操作系統實戰筆記
- 01 程序的運行過程:從代碼到機器運行
- 02 幾行匯編幾行C:實現一個最簡單的內核
- 03 黑盒之中有什么:內核結構與設計
- Rust
- 入門:Rust開發一個簡單的web服務器
- Rust的引用和租借
- 函數與函數指針
- Rust中如何面向對象編程
- 構建單線程web服務器
- 在服務器中增加線程池提高吞吐
- Java
- 并發編程
- 并發基礎
- 1.創建并啟動線程
- 2.java線程生命周期以及start源碼剖析
- 3.采用多線程模擬銀行排隊叫號
- 4.Runnable接口存在的必要性
- 5.策略模式在Thread和Runnable中的應用分析
- 6.Daemon線程的創建以及使用場景分析
- 7.線程ID,優先級
- 8.Thread的join方法
- 9.Thread中斷Interrupt方法學習&采用優雅的方式結束線程生命周期
- 10.編寫ThreadService實現暴力結束線程
- 11.線程同步問題以及synchronized的引入
- 12.同步代碼塊以及同步方法之間的區別和關系
- 13.通過實驗分析This鎖和Class鎖的存在
- 14.多線程死鎖分析以及案例介紹
- 15.線程間通信快速入門,使用wait和notify進行線程間的數據通信
- 16.多Product多Consumer之間的通訊導致出現程序假死的原因分析
- 17.使用notifyAll完善多線程下的生產者消費者模型
- 18.wait和sleep的本質區別
- 19.完善數據采集程序
- 20.如何實現一個自己的顯式鎖Lock
- 21.addShutdownHook給你的程序注入鉤子
- 22.如何捕獲線程運行期間的異常
- 23.ThreadGroup API介紹
- 24.線程池原理與自定義線程池一
- 25.給線程池增加拒絕策略以及停止方法
- 26.給線程池增加自動擴充,閑時自動回收線程的功能
- JVM
- C&C++
- GDB調試工具筆記
- C&C++基礎
- 一個例子理解C語言數據類型的本質
- 字節順序-大小端模式
- Php
- Php源碼閱讀筆記
- Swoole相關
- Swoole基礎
- php的五種運行模式
- FPM模式的生命周期
- OSI網絡七層圖片速查
- IP/TCP/UPD/HTTP
- swoole源代碼編譯安裝
- 安全相關
- MySql
- Mysql基礎
- 1.事務與鎖
- 2.事務隔離級別與IO的關系
- 3.mysql鎖機制與結構
- 4.mysql結構與sql執行
- 5.mysql物理文件
- 6.mysql性能問題
- Docker&K8s
- Docker安裝java8
- Redis
- 分布式部署相關
- Redis的主從復制
- Redis的哨兵
- redis-Cluster分區方案&應用場景
- redis-Cluster哈希虛擬槽&簡單搭建
- redis-Cluster redis-trib.rb 搭建&原理
- redis-Cluster集群的伸縮調優
- 源碼閱讀筆記
- Mq
- ELK
- ElasticSearch
- Logstash
- Kibana
- 一些好玩的東西
- 一次折騰了幾天的大華攝像頭調試經歷
- 搬磚實用代碼
- python讀取excel拼接sql
- mysql大批量插入數據四種方法
- composer好用的鏡像源
- ab
- 環境搭建與配置
- face_recognition本地調試筆記
- 虛擬機配置靜態ip
- Centos7 Init Shell
- 發布自己的Composer包
- git推送一直失敗怎么辦
- Beyond Compare過期解決辦法
- 我的Navicat for Mysql
- 小錯誤解決辦法
- CLoin報錯CreateProcess error=216
- mysql error You must reset your password using ALTER USER statement before executing this statement.
- VM無法連接到虛擬機
- Jetbrains相關
- IntelliJ IDEA 筆記
- CLoin的配置與使用
- PhpStormDocker環境下配置Xdebug
- PhpStorm advanced metadata
- PhpStorm PHP_CodeSniffer