# JAVA之旅(十二)——Thread,run和start的特點,線程運行狀態,獲取線程對象和名稱,多線程實例演示,使用Runnable接口
* * *
> 開始挑戰一些難度了,線程和I/O方面的操作了,繼續堅持
## 一.Thread
> 如何在自定義的代碼中,自定義一個線程呢?

> 我們查看API文檔,我們要啟動一個線程,先實現一個子類,
~~~
package com.lgl.hellojava;
public class MyThread extends Thread {
@Override
public void run() {
System.out.println("我是一個線程");
}
}
~~~
> 我們要調用它的話,只需要start就可以
~~~
MyThread thread = new MyThread();
thread.start();
~~~
> 這樣就會執行我們的run方法

> 我們來理一下思路,線程有兩種創建方式,我們先將第一種:
* 1.繼承Thread 類
* 2.復寫Thread類的run方法
* 3.調用線程的start方法?
* 該方法有兩個作用,啟動線程和調用run方法
> 我們可以把代碼改一下
~~~
package com.lgl.hellojava;
//公共的 類 類名
public class HelloJJAVA {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
for (int i = 0; i < 1140; i++) {
System.out.println("Hello JAVA");
}
}
}
class MyThread extends Thread {
@Override
public void run() {
for (int i = 0; i < 1140; i++) {
System.out.println("我是一個線程");
}
}
}
~~~
> 這樣輸出多少?

> 你注意一下,他們交叉輸出了,這種,就是多線成,兩個線程同時在跑,都在獲取cpu的使用權,cpu執行到誰,誰就執行,明確一點,在某一個時刻,只能有一個程序在運行(多核除外),cpu在做著快速的切換以達到看上去是同時運行的效果
>
> 我們可以形象的把多線成的運行,形容為在互相搶奪CPU的資源,那么這就是多線成的一個特性叫隨機性,誰搶到誰執行,但是執行多長,cpu說了算
## 二.run和start的特點
> 為什么要覆蓋run方法
>
> Thread類用于描述線程,該類就定義了一個功能,用于存儲線程要運行的代碼,該存儲功能就是run方法
>
> 也就是說Thread類匯總的run方法是用于存儲線程執行的代碼
>
> 目的:將自定義的代碼存儲在run方法中讓線程運行
## 三.線程運行狀態
> 線程運行會有幾種狀態,我們要了解他的狀態,才能了解他運行的原理,我們先來看一張圖

> 我們一步步來分析,首先線程的第一種狀態是創建,你new一個線程就是被創建了,緊接著,就是運行的狀態,他們的過程,就是start,當然,線程還有一種為凍結,處于某一種狀態,就交凍結,他們通過sleep來交替。最后就是線程結束了,通過stop,當然,還有其他一些狀態,比如阻塞,這是臨時狀態,這是具備運行資格,但是沒有執行權
## 四.獲取線程對象和名稱
> 線程都是有名稱的,通過格式Thread-編號來區分,我們可以這樣來驗證
~~~
package com.lgl.hellojava;
//公共的 類 類名
public class HelloJJAVA {
public static void main(String[] args) {
MyThread thread = new MyThread();
thread.start();
}
}
class MyThread extends Thread {
@Override
public void run() {
System.out.println("線程名稱:"+this.getName());
}
}
~~~
> 它輸出的結果就是

> 他是從0開始,當然,他既然有getrName,那肯定有setName方法,其實他初始化的時候就有方法,父類已經給我們提供好了
~~~
package com.lgl.hellojava;
//公共的 類 類名
public class HelloJJAVA {
public static void main(String[] args) {
MyThread thread = new MyThread("hello");
thread.start();
}
}
class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println("線程名稱:"+this.getName());
}
}
~~~
> 那么我們輸出的結果

> 它還可以通過Thread.currentThread()來獲取對象名稱,它等同于this.getName();
## 五.多線程實例演示
> 我們來一個簡單的實例來結束本篇blog,那就是賣票了,很多窗口都能賣票,這就是同時運行
~~~
package com.lgl.hellojava;
import javax.security.auth.callback.TextInputCallback;
//公共的 類 類名
public class HelloJJAVA {
public static void main(String[] args) {
/**
* 需求:簡單的賣票程序,多個線程同時賣票
*/
MyThread my1 = new MyThread();
MyThread my2 = new MyThread();
MyThread my3 = new MyThread();
MyThread my4 = new MyThread();
my1.start();
my2.start();
my3.start();
my4.start();
}
}
/**
* 賣票程序
*
* @author LGL
*
*/
class MyThread extends Thread {
// 票數
private int tick = 100;
@Override
public void run() {
while (true) {
if (tick > 0) {
System.out.println(currentThread().getName()+"賣票:" + tick--);
}
}
}
}
~~~
> 我們這樣就實現了票賣了,但是這里出了一個問題,四個線程,他一共賣了400張票,那可不行,火車就一百張票,這是不符合規則的,我們需要怎么改?讓四個對象共享一個票數,那我們就需要靜態了
~~~
// 票數
private static int tick = 100;
~~~
> 但是我們一般不定義靜態,他的生命周期有點長,我們換一種角度考慮,其實這就關乎到創建方法了,我們在之前就講個,線程創建有兩種方法。
## 六.Runnable接口
> 我們需要使用第二種方法,所以是這樣寫的,實現Runnable的接口
~~~
package com.lgl.hellojava;
import javax.security.auth.callback.TextInputCallback;
//公共的 類 類名
public class HelloJJAVA {
public static void main(String[] args) {
/**
* 需求:簡單的賣票程序,多個線程同時賣票
*/
MyThread myThread = new MyThread();
Thread t1 = new Thread(myThread);
Thread t2 = new Thread(myThread);
Thread t3 = new Thread(myThread);
Thread t4 = new Thread(myThread);
t1.start();
t2.start();
t3.start();
t4.start();
}
}
/**
* 賣票程序
*
* @author LGL
*
*/
class MyThread implements Runnable {
// 票數
private int tick = 100;
@Override
public void run() {
while (true) {
if (tick > 0) {
System.out.println("賣票:" + tick--);
}
}
}
}
~~~
> 我們得到的輸出結果就正確了

> 創建線程的第二種方式,實現Runnable接口
* 1.定義類實現Runnable接口
* 2.覆蓋Runnable接口的run方法?
* 將線程要運行的代碼存放在該run方法中
* 3.通過Thread類建立線程對象
* 4.將Runnable接口的子類對象作為實際參數傳遞給Thread類的構造函數?
* 為什么要將Runnable接口的子類對象傳遞給Thread的構造函數,因為,自定義的run方法所屬的對象是Runnable接口的子類對象,所以要讓線程去指定對象的run方法,就必須明確該run方法所屬的對象
* 5.調用Thread類的start方法開啟線程并調用Runnable接口的run方法
> 這兩種方式有什么區別呢?
* 實現方式好處,避免了單繼承的局限性,在定義線程時,建議使用實現方式
* 線程代碼存放的位置不一樣
### 小伙伴們有沒有對線程了解的更深刻一點呢?不明白沒關系,我們下篇還是接著講線程,如果有興趣可以加入群:555974449,歡迎一起交流
版權聲明:本文為博主原創文章,博客地址:http://blog.csdn.net/qq_26787115,未經博主允許不得轉載。
- 0-發現
- AndroidInterview-Q-A
- Android能讓你少走彎路的干貨整理
- LearningNotes
- temp
- temp11
- 部分地址
- 0-待辦任務
- 待補充列表
- 0-未分類
- AndroidView事件分發與滑動沖突處理
- Spannable
- 事件分發機制詳解
- 1-Java
- 1-Java-01基礎
- 未歸檔
- 你應該知道的JDK知識
- 集合框架
- 1-Java-04合集
- Java之旅0
- Java之旅
- JAVA之旅01
- JAVA之旅02
- JAVA之旅03
- JAVA之旅04
- JAVA之旅05
- JAVA之旅06
- JAVA之旅07
- JAVA之旅08
- JAVA之旅09
- java之旅1
- JAVA之旅10
- JAVA之旅11
- JAVA之旅12
- JAVA之旅13
- JAVA之旅14
- JAVA之旅15
- JAVA之旅16
- JAVA之旅17
- JAVA之旅18
- JAVA之旅19
- java之旅2
- JAVA之旅20
- JAVA之旅21
- JAVA之旅22
- JAVA之旅23
- JAVA之旅24
- JAVA之旅25
- JAVA之旅26
- JAVA之旅27
- JAVA之旅28
- JAVA之旅29
- java之旅3
- JAVA之旅30
- JAVA之旅31
- JAVA之旅32
- JAVA之旅33
- JAVA之旅34
- JAVA之旅35
- 1-Java-05辨析
- HashMapArrayMap
- Java8新特性
- Java8接口默認方法
- 圖解HashMap(1)
- 圖解HashMap(2)
- 2-Android
- 2-Android-1-基礎
- View繪制流程
- 事件分發
- AndroidView的事件分發機制和滑動沖突解決
- 自定義View基礎
- 1-安卓自定義View基礎-坐標系
- 2-安卓自定義View基礎-角度弧度
- 3-安卓自定義View基礎-顏色
- 自定義View進階
- 1-安卓自定義View進階-分類和流程
- 10-安卓自定義View進階-Matrix詳解
- 11-安卓自定義View進階-MatrixCamera
- 12-安卓自定義View進階-事件分發機制原理
- 13-安卓自定義View進階-事件分發機制詳解
- 14-安卓自定義View進階-MotionEvent詳解
- 15-安卓自定義View進階-特殊形狀控件事件處理方案
- 16-安卓自定義View進階-多點觸控詳解
- 17-安卓自定義View進階-手勢檢測GestureDetector
- 2-安卓自定義View進階-繪制基本圖形
- 3-安卓自定義View進階-畫布操作
- 4-安卓自定義View進階-圖片文字
- 5-安卓自定義View進階-Path基本操作
- 6-安卓自定義View進階-貝塞爾曲線
- 7-安卓自定義View進階-Path完結篇偽
- 8-安卓自定義View進階-Path玩出花樣PathMeasure
- 9-安卓自定義View進階-Matrix原理
- 通用類介紹
- Application
- 2-Android-2-使用
- 2-Android-02控件
- ViewGroup
- ConstraintLayout
- CoordinatorLayout
- 2-Android-03三方使用
- Dagger2
- Dagger2圖文完全教程
- Dagger2最清晰的使用教程
- Dagger2讓你愛不釋手-終結篇
- Dagger2讓你愛不釋手-重點概念講解、融合篇
- dagger2讓你愛不釋手:基礎依賴注入框架篇
- 閱讀筆記
- Glide
- Google推薦的圖片加載庫Glide:最新版使用指南(含新特性)
- rxjava
- 這可能是最好的RxJava2.x入門教程完結版
- 這可能是最好的RxJava2.x入門教程(一)
- 這可能是最好的RxJava2.x入門教程(三)
- 這可能是最好的RxJava2.x入門教程(二)
- 這可能是最好的RxJava2.x入門教程(五)
- 這可能是最好的RxJava2.x入門教程(四)
- 2-Android-3-優化
- 優化概況
- 各種優化
- Android端秒開優化
- apk大小優化
- 內存分析
- 混淆
- 2-Android-4-工具
- adb命令
- 一鍵分析Android的BugReport
- 版本控制
- git
- git章節簡述
- 2-Android-5-源碼
- HandlerThread 源碼分析
- IntentService的使用和源碼分析
- 2-Android-9-辨析
- LRU算法
- 什么是Bitmap
- 常見圖片壓縮方式
- 3-Kotlin
- Kotlin使用筆記1-草稿
- Kotlin使用筆記2
- kotlin特性草稿
- Kotlin草稿-Delegation
- Kotlin草稿-Field
- Kotlin草稿-object
- 4-JavaScript
- 5-Python
- 6-Other
- Git
- Gradle
- Android中ProGuard配置和總結
- gradle使用筆記
- Nexus私服搭建
- 編譯提速最佳實踐
- 7-設計模式與架構
- 組件化
- 組件化探索(OKR)
- 1-參考列表
- 2-1-組件化概述
- 2-2-gradle配置
- 2-3-代碼編寫
- 2-4-常見問題
- 2-9-值得一讀
- 8-數據結構與算法
- 0臨時文件
- 漢諾塔
- 8-數據-1數據結構
- HashMap
- HashMap、Hashtable、HashSet 和 ConcurrentHashMap 的比較
- 遲到一年HashMap解讀
- 8-數據-2算法
- 1個就夠了
- Java常用排序算法(必須掌握的8大排序算法)
- 常用排序算法總結(性能+代碼)
- 必須知道的八大種排序算法(java實現)
- 9-職業
- 閱讀
- 書單
- 面試
- 面試-01-java
- Java面試題全集駱昊(上)
- Java面試題全集駱昊(下)
- Java面試題全集駱昊(中)
- 面試-02-android
- 40道Android面試題
- 面試-03-開源源碼
- Android圖片加載框架最全解析(二),從源碼的角度理解Glide的執行流程
- 面試-07-設計模式
- 面試-08-算法
- 面試-09-其他
- SUMMARY
- 版權說明
- temp111