概念
一、線程:Thread
進程: 正在進行的程序,是系統進行資源分配和調度的一個獨立單位,擁有獨立的內存空間和系統資源
多進程: 多個程序在運行
線程: 就是進程中一個負責程序執行的控制單元。
多線程: 一個進程中可以有多個執行路徑 稱爲多線程。多線程就是最大化的提高CPU的利用率,它可與同屬一個進程的其他的線程共享進程所擁有的
全部資源.
其他:一個進程當中至少要有一個線程。
開啓多個線程,是爲了同時運行多個任務
每一個線程都有自己運行的內容,這個內容可以稱爲線程要執行的任務
二、創建線程
線程執行需要擁有CPU,如果線程未獲得CPU則該線程處於等待狀態
1.繼承: Thread
2.重寫:run
3.創建線程對象
4.啓動:start()-->其實就是執行run方法,
但是不一定會立馬執行,只有等當前線程獲得CPU執行權纔會真正執行
通過實現接口創建線程
1.實現接口:java.lang.Runnable
2.重寫方法:run
3.創建線程對象:
Thread t = new Thread(實現接口的對象)
4.啓動線程:start()
三、線程的生命週期
新生狀態:線程對象被創建出來
可運行狀態:線程處理裝備轉換,只是缺少CPU執行權
start()
運行運行狀態:
阻塞狀態:線程處於等待狀態,並且釋放CPU執行權
sleep():等待狀態,並且釋放CPU執行權
wait():等待狀態,擁有CPU執行權
死亡狀態:線程結束
stop()
run方法執行結束
四、同步:多線程訪問同一份資源所產生的衝突
synchronized
1.代碼塊
任何一對象都有鎖功能
synchronized(鎖對象){
//執行的代碼
}2.方法:在方法前加synchronized
a.非靜態方法的鎖對象是當前類對象
b.靜態方法的鎖對象是當前字節碼文件對象
五、線程同步的面試題
StringBuilder:非線程安全
StringBuffer:線程安全
ArrayList:非線程安全
Vector:線程安全
HashMap:非線程安全
Hashtable:線程安全
實例
sleep阻斷
package com.ibeifeng;
public class Demo {
public static void main(String[] args) {
InterruptThread1 it = new InterruptThread1();
it.start();//it線程啓動,會被阻塞100秒,然後運行
it.interrupt();//調用中斷方法,會結束阻塞狀態,拋出中斷異常
}
}
class InterruptThread1 extends Thread {
public InterruptThread1() {}
@Override
public void run() {
try {
System.out.println("線程"+getName()+"準備睡20秒,再運行");
sleep(20000);
} catch (InterruptedException e) {
System.err.println("阻塞狀態,中斷信號");
}
for(int i=0; i<100; i++) {
System.out.println(getName()+"正在運行中。。。");
}
}
}
設置優先級
package com.ibeifeng;
public class PriorityDemo {
public static void main(String[] args) {
MyThread mt1 = new MyThread("aaa");
MyThread mt2 = new MyThread("bbb");
MyThread mt3 = new MyThread("ccc");
//設置優先級
mt1.setPriority(Thread.MAX_PRIORITY);
mt2.setPriority(Thread.MIN_PRIORITY);
mt3.setPriority(Thread.NORM_PRIORITY);
mt1.start();//注意和run()的區別
mt2.start();
mt3.start();
}
}
//1繼承Thread
class MyThread extends Thread {
public MyThread(String name) {
super(name);
}
@Override
public void run() {
for(int i=0; i<10; i++) {
try {
sleep(2000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println(getName()+":,"+getPriority()+","+i);
}
}
}
join
package com.ibeifeng;
public class JoinDemo {
public static void main(String[] args) {
JoinThread jt = new JoinThread();
//創建3條線程
Thread t1 = new Thread(jt);
Thread t2 = new Thread(jt);
Thread t3 = new Thread(jt);
//運行
t1.start();
//join方法
try {
t1.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
t2.start();
t3.start();
}
}
class JoinThread implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
中斷方法
package com.ibeifeng;
public class InterruptDemo {
public static void main(String[] args) {
InterruptThread it = new InterruptThread("旺財");
it.start();
//調用中斷方法
it.interrupt();
}
}
class InterruptThread extends Thread {
public InterruptThread(String name) {
super(name);
}
@Override
public void run() {
System.out.println("休息100秒");
try {
sleep(100000);
} catch (InterruptedException e) {
System.err.println("拋出終端異常");
}
for(int i=0; i<10; i++) {
System.out.println();
}
}
}
客戶端服務器交互
客戶端
package com.ibeifeng3;
import java.io.BufferedReader;
import java.io.BufferedWriter;
import java.io.IOException;
import java.io.InputStreamReader;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientDemo {
public static void main(String[] args) {
try {
test1();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//循環向服務端發送消息
public static void test1() throws UnknownHostException, IOException {
//創建客戶端socket對象
Socket socket = new Socket("localhost",10086);
//獲取鍵盤輸入
BufferedReader br = new BufferedReader(new InputStreamReader(System.in));
//獲取向服務器的寫入流
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(os));
//鍵盤輸入字符串,寫到服務器
while(true) {
System.out.println("請輸入一個字符串");
String str = br.readLine();
System.out.println(str);
//退出條件,輸入“再見”
if(str!=null&&str.equals("再見")) {
break;
}
bw.write(str);
bw.newLine();
bw.flush();
}
//3關閉資源
socket.close();
}
public static void test() throws UnknownHostException, IOException {
//創建客戶端socket對象
Socket socket = new Socket("localhost",10086);
//獲取向服務器的寫入流
OutputStream os = socket.getOutputStream();
BufferedWriter bw = new BufferedWriter(
new OutputStreamWriter(os));
bw.write("你好嗎,你吃了嗎");
bw.flush();
//3關閉資源
socket.close();
}
}
服務端
package com.ibeifeng3;
import java.io.BufferedReader;
import java.io.IOException;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.ServerSocket;
import java.net.Socket;
//字符流給服務器發送消息
public class ServerDemo {
public static void main(String[] args) {
try {
test1();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
//循環讀取客戶端的消息
public static void test1() throws IOException {
//1 創建一個服務端的Socket對象
ServerSocket server = new ServerSocket(10086);
System.out.println("服務器啓動");
//2 監聽客戶端的連接
Socket socket = server.accept();
//3 建立客戶端的輸入通道
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
String line = null;
while((line=br.readLine())!=null) {
System.out.println(line);
}
//4 釋放相關的資源
// is.close();
socket.close();
}
public static void test() throws IOException {
//1 創建一個服務端的Socket對象
ServerSocket server = new ServerSocket(10086);
System.out.println("服務器啓動");
//2 監聽客戶端的連接
Socket socket = server.accept();
//3 建立客戶端的輸入通道
InputStream is = socket.getInputStream();
BufferedReader br = new BufferedReader(new InputStreamReader(is));
System.out.println(br.readLine());//顯示客戶端發送的內容
//4 釋放相關的資源
// is.close();
socket.close();
}
}
簡易版服務器交互
服務端
package com.ibeifeng2;
import java.io.IOException;
import java.io.InputStream;
import java.net.ServerSocket;
import java.net.Socket;
//網絡通信, --->ip ,---->端口 (前1024不要使用)
public class ServerDemo {
public static void main(String[] args) {
try {
test();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
public static void test() throws IOException {
//1 服務端的socket對象
ServerSocket server = new ServerSocket(12345);
System.out.println("服務器啓動");
//2 監聽12345端口,接受客戶端的連接
Socket socket = server.accept();//阻塞
//3 建立客戶端的寫入通道
InputStream is = socket.getInputStream();
byte[] byts = new byte[1024];
is.read(byts);
System.out.println(new String(byts));
//4 關閉資源
socket.close();
}
}
客戶端
package com.ibeifeng2;
import java.io.IOException;
import java.io.OutputStream;
import java.net.Socket;
import java.net.UnknownHostException;
public class ClientDemo {
public static void main(String[] args) {
try {
test();
} catch (UnknownHostException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
private static void test() throws UnknownHostException, IOException {
// 1 創建客戶端的 socket對象
Socket socket = new Socket("localhost", 12345);
// 2 獲取寫入流對象
OutputStream fos = socket.getOutputStream();
fos.write("你喫飯了嗎".getBytes());
// 關閉資源
fos.close();
socket.close();
}
}
同步異步
同步1
package com.ibeifeng1;
//異步產生的問題
public class AsyncronizeDemo {
//取款 --存款1百萬,主卡副卡分別取錢,每次各取1萬,取完爲止
public static void main(String[] args) {
//創建兩個線程分別模擬主卡、副卡
DrawMoneyThread mainCard = new DrawMoneyThread("主卡");
DrawMoneyThread secondCard = new DrawMoneyThread("副卡");
mainCard.start();
secondCard.start();
}
}
class DrawMoneyThread extends Thread {
public DrawMoneyThread(String name) {
super(name);
}
static int deposit = 100;//存款100萬
int money;
@Override
public void run() {
while(deposit>0) {
deposit--;
money++;
System.out.println(getName()+"取款1萬,"+"剩餘"+deposit);
}
}
}
同步2
package com.ibeifeng1;
//解決賣票的問題, 使用同步
//模擬賣票窗口,同時賣票,出現重票,負票
public class AsyncronizeDemo1 {
public static void main(String[] args) {
SellTicket st1 = new SellTicket("窗口1");
SellTicket st2 = new SellTicket("窗口2");
SellTicket st3 = new SellTicket("窗口3");
st1.start();
st2.start();
st3.start();
}
}
class SellTicket extends Thread {
static int tickets = 100;
public SellTicket(String name) {
super(name);
}
@Override
public void run() {
while(true) {
System.out.println(getName()+" 賣出第"+tickets+"張票");
tickets--;
if(tickets<=0) {
break;
}
}
}
}
同步3
package com.ibeifeng1;
//同步代碼,使用Synchronized關鍵字解決同步問題
public class SynchronizedDemo {
public static void main(String[] args) {
SellTicket1 st = new SellTicket1("1窗口");
SellTicket1 st1 = new SellTicket1("2窗口");
st.start();
st1.start();
}
}
class SellTicket1 extends Thread {
static int tickets = 100;
private static Object obj = new Object();
public SellTicket1(String name) {
super(name);
}
@Override
public void run() {
boolean flag = true;
while (flag) {
flag = sellTickets_static();
}
}
//靜態同步方法 ---- 》靜態方法的鎖對象是 類相關信息的對象,理解爲字節碼文件
private static synchronized boolean sellTickets_static() {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " 賣出第" + tickets + "張票");
tickets--;
}
if(tickets<=0) {
return false;
}
return true;
}
//非靜態同步方法 ---- 》非靜態方法的鎖對象是 this,也即 當前對象
private synchronized boolean sellTickets() {
if (tickets > 0) {
System.out.println(getName() + " 賣出第" + tickets + "張票");
tickets--;
}
if(tickets<=0) {
return false;
}
return true;
}
}
使用Synchronized關鍵字解決同步問題
package com.ibeifeng1;
//同步代碼,使用Synchronized關鍵字解決同步問題
public class SynchronizedDemo1 {
public static void main(String[] args) {
SellTicket4 st = new SellTicket4("1窗口");
SellTicket4 st1 = new SellTicket4("2窗口");
st.start();
st1.start();
}
}
class SellTicket4 extends Thread {
static int tickets = 100;
private static Object obj = new Object();
public SellTicket4(String name) {
super(name);
}
@Override
public void run() {
boolean flag = true;
while (flag) {
// 傳一個對象,作爲鎖對象
synchronized (obj) { //SellTicket4.class
if (tickets > 0) {
System.out.println(getName() + " 賣出第" + tickets + "張票");
tickets--;
}
}
if(tickets<=0) {
flag = false;
}
}
}
}
同步5
package com.ibeifeng1;
public class SynchronizedDemo2 {
public static void main(String[] args) {
SellTicket3 st = new SellTicket3();
Thread t = new Thread(st);
Thread t1 = new Thread(st);
t.start();
t1.start();
}
}
class SellTicket3 implements Runnable {
static int tickets = 100;
@Override
public void run() {
boolean flag = true;
while (flag) {
flag = sellTickets();
}
}
//非靜態同步方法 ---- 》非靜態方法的鎖對象是 this,也即 當前對象
private synchronized boolean sellTickets() {
if (tickets > 0) {
System.out.println(Thread.currentThread().getName() + " 賣出第" + tickets + "張票");
tickets--;
}
if(tickets<=0) {
return false;
}
return true;
}
}