Java進階總結——線程

Java進階總結——線程

1.進程

/**

 * java中啓動進程的兩種方式

 * 1.RunTime,運行時類

 * 2.ProcessBuilder類

 * */

 

package day24.process;

 

import java.io.IOException;

public class ProcessDemo {

 

public static void main(String[] args) throws IOException {

/*//1通過運行時類

Runtime time=Runtime.getRuntime();

//執行要打開的進程

time.exec("notepad");

time.exec("D:\\TSBrowserDownloads\\cmder\\Cmder.exe");

*/

//2通過進程生成器啓動進程

ProcessBuilder builder=new ProcessBuilder("notepad");

//啓動進程

builder.start();

}

}

運行結果:

啓動應用程序!

 

2.線程的實現

2.1繼承Thread

 

 /**

 * ThreadDemo繼承了Thread

 * 你什麼該類就是一個線程類

 * 必須在子類中重寫run方法

 * run方法是線程體

 *  * */

 

package day24.thread;

public class ThreadDemo extends Thread{

@Override

public void run() {

// 線程體

try {

Thread.sleep(1000);//休眠1s

} catch (InterruptedException e) {

// TODO 自動生成的 catch 塊

e.printStackTrace();

}

//獲取線程名稱

System.out.println(Thread.currentThread().getName());

}

public static void method() {

//獲取當前線程

System.out.println(Thread.currentThread().getName());

}

public static void main(String[] args) {

// 1.獲取當前線程

Thread th=Thread.currentThread();

//2.查看當前線程

System.out.println("名稱:"+th.getName());//名稱

System.out.println("狀態:"+th.getState());//狀態

System.out.println("ID:"+th.getId());//ID

System.out.println("優先級:"+th.getPriority());//優先級

method();

//3.創建一個子線程,啓動了一個線程,其實做了一個異步操作

ThreadDemo th1=new ThreadDemo();

//給線程命名

th1.setName("尊");

//啓動線程  不能直接調用run方法,必須通過start來調用

th1.start();

System.out.println("執行完畢!");

}

}

輸出結果:

2.2實現Runnable接口

/**

 * ThreadDemo1實現Runnable這個接口

 * ThreadDemo1不是線程類

 * */

 

package day24.thread;

public class ThreadDemo1 implements Runnable{

@Override

public void run() {

// 線程體

System.out.println("線程名稱:"+Thread.currentThread().getName());

 

}

public static void main(String[] args) {

//創建一個ThreadDemo1的實例

ThreadDemo1 demo=new ThreadDemo1();

//創建一個線程對象,執行demo對象

Thread th=new Thread(demo,"qq");

//啓動線程

th.start();

//再次啓動一個線程

Thread th1=new Thread(demo,"ww");

th1.start();

}

}

 

3.線程的方法

3.1基本方法

3.1.1線程優先級

package day25.thread;

 

public class ThreadDemo extends Thread{

@Override

public void run() {

for (int i = 0; i < 120; i++) {

System.out.println(Thread.currentThread().getName()+"\t優先級:"+Thread.currentThread().getPriority());

 

}

}

 

public static void main(String[] args) {

//初始三個線程

ThreadDemo demo=new ThreadDemo();

ThreadDemo demo1=new ThreadDemo();

ThreadDemo demo2=new ThreadDemo();

//命名

demo.setName("A");

demo1.setName("B");

demo2.setName("C");

//設置優先級1-5  默認是5

demo.setPriority(MIN_PRIORITY);

demo1.setPriority(MAX_PRIORITY);

 

//啓動

demo.start();

demo1.start();

demo2.start();

}

}

輸出結果:

3.1.2線程狀態

package day25.thread;

 

public class ThreadDemo2 extends Thread{

@Override

public void run() {

System.out.println("運行狀態:"+Thread.currentThread().getState()+"\t激活:"+Thread.currentThread().isAlive());

}

 

@SuppressWarnings("static-access")

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

//初始化對象

ThreadDemo2 demo2=new ThreadDemo2();

System.out.println("創建狀態:"+demo2.getState()+"\t\t激活:"+demo2.isAlive());

//啓動線程

demo2.start();

System.out.println("啓動狀態:"+demo2.getState()+"\t激活:"+demo2.isAlive());

demo2.sleep(2000);

System.out.println("完畢狀態:"+demo2.getState()+"\t激活:"+demo2.isAlive());

}

}

輸出結果:

3.1.3線程同步

package day25.thread;

 

public class ThreadDemo1 extends Thread{

@Override

public void run() {

try {

System.out.println("生日快樂");

Thread.sleep(2000);

} catch (InterruptedException e) {

// TODO 自動生成的 catch 塊

e.printStackTrace();

}

System.out.println("七夕快樂!");

}

 

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

// 初始化對象

ThreadDemo1 demo1=new ThreadDemo1();

 

//啓動線程

demo1.start();

//合併線程,demo1和主線程合併

//demo1.join();//join在start之後使用

//主線程執行方法

for (int i = 0; i < 10; i++) {

Thread.sleep(200);

if (i==3) {

demo1.join();

}

System.out.println("i====="+i);

}

}

}

輸出結果:

3.1.4線程禮讓

 

package day25.thread;

 

public class ThreadDemo3 implements Runnable{

@SuppressWarnings("static-access")

@Override

public void run() {

for (int i = 0; i < 6; i++) {

if (i==3) {

//禮讓線程

Thread.currentThread().yield();

System.out.println("禮讓");

}

System.out.println("i=="+i+"  "+Thread.currentThread().getName());

}

}

public static void main(String[] args) {

// 初始化對象

ThreadDemo3 demo3=new ThreadDemo3();

//創建線程

Thread th1=new Thread(demo3,"qq");

Thread th2=new Thread(demo3,"rr");

Thread th3=new Thread(demo3,"uu");

//啓動線程

th1.start();

th2.start();

th3.start();

}

}

輸出結果:

3.1.5線程守護

package day25.thread;

 

public class ThreadDaemonDemo extends Thread{

@Override

public void run() {

while (true) {

try {

Thread.sleep(500);

} catch (InterruptedException e) {

e.printStackTrace();

}

System.out.println("七夕節快樂");

}

}

 

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

//創建對象

ThreadDaemonDemo demo=new ThreadDaemonDemo();

//把當前線程設爲守護線程,需要在啓動之前設置

demo.setDaemon(true);

//啓動線程

demo.start();

System.out.println("不快樂!");

Thread.sleep(3000);

System.out.println("喝酒");

}

}

輸出結果:

3.2鎖

3.2.1synchronized修飾符

/**

 * synchronized修飾符

 * 可以修飾方法,鎖住的是當前對象this

 * 可以修飾代碼塊

 * 同步的意思

 * */

 

package day25.thread;

 

public class AppleDemo implements Runnable {

//蘋果數量

private int count=50;

private static Object obj=new Object();

//修飾方法修飾的是this對象

public synchronized void method(){

if (count>0) {

System.out.println(Thread.currentThread().getName()+"1吃了第"+count+"個蘋果");

count--;

}

}

public void method1() {

synchronized (obj) {//同步代碼塊,作用域精確

if (count>0) {

System.out.println(Thread.currentThread().getName()+"2吃了第"+count+"個蘋果");

count--;

}

}

}

@Override

public void run() {

// 吃蘋果

for (int i = 0; i < 50; i++) {

//method();

method1();

}

}

 

public static void main(String[] args) {

// 初始化對象

AppleDemo demo=new AppleDemo();

//創建線程,啓動線程

Thread th1=new Thread(demo,"A");

th1.start();

Thread th2=new Thread(demo,"B");

th2.start();

Thread th3=new Thread(demo,"C");

th3.start();

}

}

輸出結果:

3.2.2互斥鎖ReentrantLock

 

package day25.thread;

 

import java.util.concurrent.locks.ReentrantLock;

 

public class AppleLock implements Runnable {

private int count=50;

//創建一個互斥鎖

ReentrantLock lock=new ReentrantLock();

@Override

public void run() {

for (int i = 0; i < 50; i++) {

//上鎖

lock.lock();

try {

if (count>0) {

System.out.println(Thread.currentThread().getName()+"吃了第"+count+"個蘋果");

count--;

}

} catch (Exception e) {

// TODO: handle exception

}finally {

//釋放鎖

lock.unlock();

}

}

}

 

public static void main(String[] args) {

// 初始化對象

AppleLock app=new AppleLock();

//啓動三個線程

new Thread(app, "A").start();

new Thread(app, "B").start();

new Thread(app, "C").start();

}

}

輸出結果:

3.2.3死鎖

package day25.thread;

//死鎖

public class DeadLockDemo implements Runnable{

//全局變量

boolean isFlag=false;

Object obj=new Object();

Object obj1=new Object();

//一個線程執行A

public void methodA() {

System.out.println("methodA=="+Thread.currentThread().getName());

synchronized (obj) {

System.out.println("obj已經加鎖");

synchronized (obj1) {

System.out.println("訪問obj1");

}

System.out.println("obj1訪問結束");

}

System.out.println("obj已經解鎖");

}

//一個線程執行B

public void methodB() {

System.out.println("methodB=="+Thread.currentThread().getName());

synchronized (obj1) {

System.out.println("----->obj1已經加鎖");

synchronized (obj) {

System.out.println("------>訪問obj");

}

System.out.println("------>obj訪問結束");

}

System.out.println("------>obj1解鎖");

}

 

@Override

public void run() {

if (!isFlag) {

isFlag=!isFlag;

methodA();

}else {

methodB();

}

}

public static void main(String[] args) {

// 創建對象

DeadLockDemo demo=new DeadLockDemo();

//啓動兩個線程

new Thread(demo, "A").start();

new Thread(demo, "B").start();

}

}

輸出結果:

3.3定時器Timer

 

package day25.timer;

 

import java.text.ParseException;

import java.text.SimpleDateFormat;

import java.util.Calendar;

import java.util.Date;

import java.util.Timer;

import java.util.TimerTask;

 

class Task extends TimerTask{

@Override

public void run() {

// 計時器要執行的任務

System.out.println("上九天攬月,下五洋捉鱉!");

}

}

 

public class TimerDemo {

 

public static void main(String[] args) throws ParseException {

// 創建一個計時器對象,可以設置爲守護線程+true

Timer timer=new Timer();

//添加執行的任務

//獲取當前時間戳

Calendar c=Calendar.getInstance();

Long times=c.getTimeInMillis();

//3s後執行

times+=3*1000;

//設置時間

c.setTimeInMillis(times);

//獲取日期

Date date=c.getTime();

//指定時間

SimpleDateFormat frm=new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

//將String類型的時間解析爲Date

date=frm.parse("2018-08-17 16:39:40");

Task ts=new Task();

timer.schedule(new Task(), date);//在指定的時間來執行指定的任務

timer.schedule(new TimerTask() {

 

@Override

public void run() {

// 執行任務

System.out.println("送你一顆小星星");

}

}, 5000);//以當前時間延遲多少毫秒執行一次任務

 

//指定首次出現時間

date=frm.parse("2018-08-17 16:45:00");

timer.schedule(new TimerTask() {

 

@Override

public void run() {

System.out.println("我不要!");

}

}, date, 10000);//在指定的時間執行任務,以一定的延時重複執行

 

timer.schedule(new TimerTask() {

 

@Override

public void run() {

System.out.println("那就分手吧!");

}

}, 2000, 5000);//以當前時間延遲多少s,再以固定的時間重複執行

 

//取消指定任務

//ts.cancel();

//取消timer內所有任務

//ts.cancel();

//清空已結束任務

//System.out.println(timer.purge());

}

}

輸出結果:

3.4單例設計模式

/**

 * 單例設計模式

 * 當前該類只能有一個對象,這個對象是共享的

 * */

3.4.1懶漢模式

 

package day25.singleton;

//懶漢模式

public class SingletonDemo {

String name;

private static SingletonDemo singleton=null;

//構造方法私有化

private SingletonDemo(){

 

}

//通過類來獲取對象,設計一個靜態的方法

public static synchronized SingletonDemo getIntance() {

//創建對象,返回對象

if (singleton==null) {

singleton=new SingletonDemo();//初始化一個對象

}

return singleton;//將對象返回到方法調用處

}

}

 

package day25.singleton;

 

public class TestDemo {

public static void main(String[] args) {

/*SingletonDemo demo=SingletonDemo.getIntance();

demo.name="zz";

System.out.println(demo);

SingletonDemo demo1=SingletonDemo.getIntance();

System.out.println(demo1);

System.out.println(demo1.name);*/

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo.getIntance());

}

}).start();;

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo.getIntance());

}

}).start();;

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo.getIntance());

}

}).start();;

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo.getIntance());

}

}).start();;

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo.getIntance());

}

}).start();;

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo.getIntance());

}

}).start();;

}

}

輸出結果:

3.4.2餓漢模式

 

package day25.singleton;

//餓漢模式

public class SingletonDemo1 {

private static final SingletonDemo1 singleton=new SingletonDemo1();

//構造方法私有化

private SingletonDemo1(){

 

}

//通過類來獲取對象,設計一個靜態的方法

public static synchronized SingletonDemo1 getIntance() {

return singleton;

}

}

 

package day25.singleton;

 

public class TestDemo1 {

 

public static void main(String[] args) {

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo1.getIntance());

}

}).start();

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo1.getIntance());

}

}).start();

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo1.getIntance());

}

}).start();

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo1.getIntance());

}

}).start();

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo1.getIntance());

}

}).start();

 

new Thread(new Runnable() {

 

@Override

public void run() {

System.out.println(SingletonDemo1.getIntance());

}

}).start();

}

}

輸出結果:

3.5生產者消費者模型

 

package day25.test;

/**

 * 生產者與消費者模型中,要保證以下幾點:

 * 1 同一時間內只能有一個生產者生產     生產方法加鎖sychronized

 * 2 同一時間內只能有一個消費者消費     消費方法加鎖sychronized

 * 3 共享空間空時消費者不能繼續消費     消費前循環判斷是否爲空,空的話將該線程wait,釋放鎖允許其他同步方法執行

 * 4 共享空間滿時生產者不能繼續生產     生產前循環判斷是否爲滿,滿的話將該線程wait,釋放鎖允許其他同步方法執行

 */

 

/**

 * 生產者: 一直生產,直到生產完10個

 * 在生產過程中,如果庫存中存滿(1個)則停止生產(由resource控制)

 */

//生產者

class  Producer implements Runnable{

private  ShareResource  resource;//共享資源對象

public Producer(ShareResource resource) {

this.resource=resource;

}

@Override

public void run() {

System.out.println("生產中。。。");

for (int prodect = 1; prodect <=100; prodect++) {

try {

resource.setProdect(prodect);

} catch (InterruptedException e) {

// TODO 自動生成的 catch 塊

e.printStackTrace();

}

}

}

}

/**

 * 消費者:不斷消費,直到消費10個

 *        消費過程中,如果庫存有包子則消費,沒包子等待(resource中wait())

 */

//消費者

class    Consumer implements Runnable{

private  ShareResource  resource;//共享資源對象

public Consumer(ShareResource resource) {

this.resource=resource;

}

@Override

public void run() {

System.out.println("消費中。。。");

for (int i = 1; i <= 100; i++) {

try {

resource.getProdect();

} catch (InterruptedException e) {

// TODO 自動生成的 catch 塊

e.printStackTrace();

}

}

}

}

/**

 * 共享資源: 負責控制庫存,如果庫存沒包子了:通知生產者開始生產(notify), 並且通知消費者等待(wait)

 *                  ,如果庫存有包子:通知生產者停止生產(wait),   並且通知消費者開始消費(notify)

 *                  notify() / notifyall() :通知 實質上相當於 喚醒

 * 加synchronized 爲了保證,同一時刻只有一個生產者在生產,只有一個消費者在消費

 */

 

//共享資源

class ShareResource{

private int prodect=-1;

 

public synchronized void setProdect(int prodect) throws InterruptedException {

waitIfFull();//如果滿,等待   被喚醒後繼續執行

this.prodect=prodect;

System.out.println("生產包子"+prodect+"個");

notify();

}

public synchronized int getProdect() throws InterruptedException {

waitIfEmpty();//如果空,等待  被喚醒後繼續執行

int p=this.prodect;

System.out.println("消費者購買了"+p+"個包子");

this.prodect=-1;

notify();

return p;

}

private synchronized void waitIfEmpty() throws InterruptedException {

if (prodect==-1) {

System.out.println("消費者等待!");

wait();

}

}

private synchronized void waitIfFull() throws InterruptedException {

if (prodect!=-1) {

System.out.println("生產者等待!");

wait();

}

}

}

 

public class ProducterComsumerDemo {

public static void main(String[] args) {

//初始化對象

ShareResource resource=new ShareResource();

//啓動線程

new Thread(new Producer(resource)).start();

new Thread(new Consumer(resource)).start();

}

}

輸出結果:

4.知識框架