多執行緒學習筆記(狂神說視訊21-28)
阿新 • • 發佈:2020-08-25
CopyOnWriteArrayList
public class TestJUC { public static void main(String[] args) throws InterruptedException { CopyOnWriteArrayList<String> list = new CopyOnWriteArrayList<>(); for (int i = 0; i < 1000; i++) { new Thread(()-> { list.add(Thread.currentThread().getName()); }).start(); } Thread.sleep(3000); System.out.println(list.size()); } }
死鎖
死鎖:多個執行緒互相抱著對方需要的資源,然後形成僵持
public class DeadLock { public static void main(String[] args) { Makeup g1 = new Makeup(1,"灰姑娘"); Makeup g2 = new Makeup(1,"白雪公主"); g1.start(); g2.start(); } } //口紅 class Lipstick{ } //鏡子 class Mirror{ } class Makeup extends Thread{ //需要的資源只有一份,所以要用static static Lipstick l = new Lipstick(); static Mirror m = new Mirror(); int choice;//選擇 String girlName;//選擇化妝品的人 Makeup(int choice,String girlName){ this.choice = choice; this.girlName = girlName; } @Override public void run() { //化妝 try { makeup(); }catch(Exception e) { e.printStackTrace(); } } //化妝,互相持有對方的鎖,就是需要拿到對方的資源 private void makeup() throws InterruptedException { if (choice == 0) { synchronized (l)//獲得口紅的鎖 { System.out.println(this.girlName + "獲得了口紅的鎖"); Thread.sleep(1000); } synchronized (m)//一秒鐘後想獲得鏡子的鎖 { System.out.println(this.girlName + "獲得鏡子的鎖"); } } else { synchronized (m)//獲得鏡子的鎖 { System.out.println(this.girlName + "獲得了鏡子的鎖"); Thread.sleep(2000); } synchronized (l)//一秒鐘後想獲得口紅的鎖 { System.out.println(this.girlName + "獲得口紅的鎖"); } } } }
執行結果
Lock鎖
import java.util.concurrent.locks.ReentrantLock; public class TestLock { public static void main(String[] args) { TestLock2 testLock2 = new TestLock2(); new Thread(testLock2).start(); new Thread(testLock2).start(); new Thread(testLock2).start(); } } class TestLock2 implements Runnable{ int ticketNums = 10; //定義Lock鎖 private final ReentrantLock lock = new ReentrantLock(); @Override public void run() { while (true){ try{ lock.lock();//加鎖 if (ticketNums >0){ try { Thread.sleep(1000); } catch (InterruptedException e) { e.printStackTrace(); } System.out.println(Thread.currentThread().getName()+"==>"+ticketNums--); }else { break; } }finally { lock.unlock();//解鎖 } } } }
執行結果
生產者消費者問題
管程法
//測試:生產者消費者模型-》利用緩衝區解決:管程法
//生產者,消費者,長跑,緩衝區
public class TestPC {
public static void main(String[] args) {
SynContainer c = new SynContainer();
new Productor(c).start();
new Consumer(c).start();
}
}
//生產者
class Productor extends Thread{
SynContainer container;
public Productor(SynContainer container) {
this.container = container;
}
//生產
@Override
public void run() {
for(int i=0;i<100;i++)
{
container.push(new Chicken(i));
System.out.println("生產了第"+i+"只雞");
}
}
}
//消費者
class Consumer extends Thread{
SynContainer container;
public Consumer(SynContainer container) {
this.container = container;
}
//消費
@Override
public void run() {
for(int i=0;i<100;i++)
{
System.out.println("消費了第"+container.pop().id+"只雞");
}
}
}
//產品
class Chicken{
int id;//編號
public Chicken(int id)
{
this.id = id;
}
}
//緩衝區
class SynContainer{
//容器大小
Chicken[] chickens = new Chicken[10];
//容器計數器
int count = 0;
//生產者放入產品
public synchronized void push(Chicken chicken)
{
//如果容器滿了,就需要等待消費者消費
if(count == chickens.length)
{
//通知消費者消費,生產等待
try {
this.wait();
}catch(Exception e) {
e.printStackTrace();
}
}
//如果沒有滿,我們就需要丟入產品
chickens[count] = chicken;
count++;
//可以通知消費者了
this.notifyAll();
}
//消費者消費產品
//消費者消費產品
public synchronized Chicken pop() {
//判斷能否消費
if(count==0)
{
//等待生產者生產,消費者等待
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
//如果可以消費
count--;
Chicken chicken = chickens[count];
//吃完了,通知生產者生產
this.notifyAll();
return chicken;
}
}
執行結果
訊號燈法
//測試生產消費者問題2,訊號燈法,標誌位解決
public class TestPC2 {
public static void main(String[] args) {
// TODO Auto-generated method stub
TV tv = new TV();
new player(tv).start();
new Watcher(tv).start();
}
}
//生產者-》演員
class player extends Thread{
TV tv;
public player(TV tv)
{
this.tv = tv;
}
@Override
public void run() {
for(int i=0;i<20;i++)
{
if(i%2==0)
{
this.tv.play("綜藝節目");
}
else
{
this.tv.play("小視訊");
}
}
}
}
//消費者-》觀眾
class Watcher extends Thread{
TV tv;
public Watcher(TV tv)
{
this.tv = tv;
}
@Override
public void run() {
for(int i=0;i<20;i++)
{
tv.watch();
}
}
}
//產品-》節目
class TV {
//演員錄製,觀眾等待
//觀眾觀看,演員等待
String voice;//表演的節目
boolean flag = true;
//錄製
public synchronized void play(String voice) {
if(!flag)
{
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("演員錄製了"+voice);
//通知觀眾觀看
this.notifyAll();
this.voice = voice;
this.flag = !this.flag;
}
//觀眾看
public synchronized void watch() {
if(flag)
{
try {
this.wait();
}catch(Exception e)
{
e.printStackTrace();
}
}
System.out.println("觀看了"+voice);
//通知演員錄製
this.notifyAll();
this.flag = !this.flag;
}
}
執行結果
執行緒池
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
//測試執行緒池
public class TestPool {
public static void main(String[] args) {
//1.建立執行緒池
ExecutorService service = Executors.newFixedThreadPool(10);
//執行
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
service.execute(new MyThread());
//關閉連線
service.shutdown();
}
}
class MyThread implements Runnable{
@Override
public void run() {
for(int i=0;i<2;i++)
{
System.out.println(Thread.currentThread().getName()+" "+i);
}
}
}
執行結果
總結
//回顧總結執行緒的建立
public class ThreadNew {
public static void main(String[] args) {
new MyThread1().start();
new Thread(new MyThread2()).start();
FutureTask<Integer> f = new FutureTask<Integer>(new MyThread3());
new Thread(f).start();
try {
Integer i = f.get();
System.out.println(i);
} catch (Exception e) {
e.printStackTrace();
}
}
}
//1.繼承Thread類
class MyThread1 extends Thread {
@Override
public void run() {
System.out.println("MyThread1");
}
}
//2.實現Runnable介面
class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("MyThread2");
}
}
//3.實現Callable介面
class MyThread3 implements Callable<Integer> {
@Override
public Integer call() throws Exception {
System.out.println("MyThread3");
return 100;
}
}