目次
プロセスとスレッド
プログラム: プログラムは、順序付けられたデータと命令の集合であり、実行する意味はなく、静的な概念です。
プロセス: プログラム実行のプロセスであり、動的な概念であり、システム リソース割り当ての単位です。
スレッド: プロセスにはさらに多くのスレッドが含まれます。もちろん、プロセスには少なくとも 1 つのスレッドがあります。スレッドは CPU のスケジューリングと実行の単位です。
[外部リンク画像の転送に失敗しました。ソース サイトにはリーチ防止メカニズムが存在する可能性があります。画像を保存して直接アップロードすることをお勧めします (img-D5XJ3X4Z-1660287821263) (C:\Users\FBM\AppData\Roaming\Typora\) typora-user-images\ image-20220708170502917.png)]
スレッドの作成
スレッドの継承 2. Runnable の実装 3. Callable の実装
package demo1;
//如何创建多线程
public class strat_thread01 extends Thread{
@Override
public void run() {
for (int i = 0; i < 20000; i++) {
System.out.println("-----------我在学习多线程");
}
}
public static void main(String[] args) {
strat_thread01 strat_thread=new strat_thread01();
//这样的话就直接调用run方法
// strat_thread.run();
// 这样的话就是同时开启多线程,里面的for循环是同时执行的。
strat_thread.start();
for (int i = 0; i < 20000; i++) {
System.out.println("------------tongshizaixuexixianchengdeke");
}
}
}
スレッド経由で画像をダウンロードする例
package demo1;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
//练习多线程下载
public class strat_thread02 extends Thread{
private String url;
private String name;
public strat_thread02(String url,String name){
this.url=url;
this.name=name;
}
@Override
public void run() {
downloadMethod download=new downloadMethod();
download.downloadMethod1(url,name);
System.out.println("您的图片已经下载完成:"+name);
}
public static void main(String[] args) {
strat_thread02 strat_thread01=new strat_thread02("https://pics5.baidu" +
".com/feed/dbb44aed2e738bd4373c0e80c6341adc267ff9a8.jpeg?token=f2ab22ff3243929b141f525f8c869371",
"image1.jpg");
strat_thread02 strat_thread02=new strat_thread02("https://img1.baidu.com/it/u=1966616150,2146512490&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1657472400&t=2bb1ed82ca4098d830b7a9354a1ca749","image2.jpg");
strat_thread02 strat_thread03=new strat_thread02("https://img2.baidu.com/it/u=1814268193,3619863984&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1657472400&t=cf13b8c38044a363e513c33ed698bb8a",
"image3.jpg");
strat_thread01.start();
strat_thread02.start();
strat_thread03.start();
}
}
class downloadMethod{
// 下载方法
public void downloadMethod1(String url,String file){
try {
FileUtils.copyURLToFile(new URL(url),new File(file));
}catch (IOException e){
e.printStackTrace();
System.out.println("IO异常,downloader方法出现异常!");
}
}
}
您的图片已经下载完成:image1.jpg
您的图片已经下载完成:image3.jpg
您的图片已经下载完成:image2.jpg
这里可以看出来下载出来的图片完成顺序是不一致的
Runnableインターフェイスを実装する
package demo1;
//如何创建多线程
public class strat_thread03 implements Runnable{
@Override
public void run() {
for (int i = 0; i < 20000; i++) {
System.out.println("-----------我在学习多线程");
}
}
public static void main(String[] args) {
strat_thread03 strat_thread=new strat_thread03();
new Thread(strat_thread).start();
for (int i = 0; i < 20000; i++) {
System.out.println("------------tongshizaixuexixianchengdeke");
}
}
}
まず、新しい Thread オブジェクトを作成し、オーバーライドされた run メソッドを実装するオブジェクトを渡して、strat() をオンにする必要があります。
継承は1つしか継承できませんが、複数のインターフェースを実装できるため、単一継承の欠点を回避できるため、この方法を使用することをお勧めします。
チケット取得の例:
package demo1;
//如何创建多线程
public class strat_thread04 implements Runnable{
private int tiket=10;
@Override
public void run() {
while (true) {
tiket--;
if (tiket <= 0) {
break;
}
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + "拿到了" + tiket + "张票");
}
}
public static void main(String[] args) {
strat_thread04 strat=new strat_thread04();
// 因为同时在运行同一个线程,所以这里会有抢占资源的情况
new Thread(strat,"小明").start();
new Thread(strat,"黄牛").start();
new Thread(strat,"张三").start();
}
}
ウサギとカメ:
package demo1;
//如何创建多线程
public class strat_thread05 implements Runnable{
private String winner;
@Override
public void run() {
while (true) {
for (int i = 0; i <= 100; i++) {
boolean isTrue =runStept(i);
if (Thread.currentThread().getName().equals("兔子")&&i%10==0){
try {
Thread.sleep(2);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("兔子跑的太快了,休息一下");
}
System.out.println(Thread.currentThread().getName() +"跑了"+i);
if (isTrue){
break;
}
}
System.out.println("胜利者是:"+winner);
return;
}
}
public boolean runStept(int step){
if (winner!=null){
return true;
}else {
if (step==100){
winner=Thread.currentThread().getName();
return true;
}
}
return false;
}
public static void main(String[] args) {
strat_thread05 strat=new strat_thread05();
// 因为同时在运行同一个线程,所以这里会有抢占资源的情况
new Thread(strat,"乌龟").start();
new Thread(strat,"兔子").start();
}
}
Callable メソッドを実装してスレッドを作成する
package demo2;
import org.apache.commons.io.FileUtils;
import java.io.File;
import java.io.IOException;
import java.net.URL;
import java.util.concurrent.*;
//练习多线程下载
public class testCallable implements Callable<Boolean> {
private String url;
private String name;
public testCallable(String url,String name){
this.url=url;
this.name=name;
}
@Override
public Boolean call() throws Exception {
downloadMethod download=new downloadMethod();
download.downloadMethod1(url,name);
System.out.println("您的图片已经下载完成:"+name);
return true;
}
public static void main(String[] args) throws ExecutionException, InterruptedException {
testCallable strat_thread01=new testCallable("https://pics5.baidu" +
".com/feed/dbb44aed2e738bd4373c0e80c6341adc267ff9a8.jpeg?token=f2ab22ff3243929b141f525f8c869371",
"image1.jpg");
testCallable strat_thread02=new testCallable("https://img1.baidu.com/it/u=1966616150,2146512490&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1657472400&t=2bb1ed82ca4098d830b7a9354a1ca749","image2.jpg");
testCallable strat_thread03=new testCallable("https://img2.baidu.com/it/u=1814268193,3619863984&fm=253&app=138&size=w931&n=0&f=JPEG&fmt=auto?sec=1657472400&t=cf13b8c38044a363e513c33ed698bb8a",
"image3.jpg");
//创建执行服务
ExecutorService es= Executors.newFixedThreadPool(3);
//提交执行
Future<Boolean> submit1 = es.submit(strat_thread01);
Future<Boolean> submit2 = es.submit(strat_thread02);
Future<Boolean> submit3 = es.submit(strat_thread03);
//获取结果
Boolean aBoolean1 = submit1.get();
Boolean aBoolean2 = submit2.get();
Boolean aBoolean3 = submit3.get();
//关闭服务
es.shutdownNow();
}
}
class downloadMethod{
// 下载方法
public void downloadMethod1(String url,String file){
try {
FileUtils.copyURLToFile(new URL(url),new File(file));
}catch (IOException e){
e.printStackTrace();
System.out.println("IO异常,downloader方法出现异常!");
}
}
}
Callable の利点:
1. 戻り値を受け入れることができます
2. 例外をスローできる
欠点: 実装は前の 2 つの方法よりも少し複雑です。
/**
* 代理对象的总结:
* 真是对象和代理对象都要实现同一个接口
* 代理对象要代理真实角色
* 好处:
* 代理对象可以做很多真实对象做不了的事情
* 真实对象专注做自己的事情
*/
public class Staticproxy {
public static void main(String[] args) {
// Weddingcompany weddingcompany=new Weddingcompany(new you());
// weddingcompany.HappyMarry();
new Thread(()-> System.out.println("lambada的写法")).start();
new Weddingcompany(new you()).HappyMarry();
}
}
interface Marry{
void HappyMarry();
}
//这个是真是对象
class you implements Marry{
@Override
public void HappyMarry() {
System.out.println("卿老师要结婚了");
}
}
//这个是代理对象
class Weddingcompany implements Marry{
private Marry target;
public Weddingcompany(Marry target) {
this.target = target;
}
@Override
public void HappyMarry() {
before();
this.target.HappyMarry(); //这就是真是的对象
after();
}
public void before(){
System.out.println("结婚之前,收尾款");
}
public void after(){
System.out.println("结婚之后,布置现场");
}
}
ラムダ式:
関数型インターフェイスの定義:
抽象 メソッドのみを含むインターフェイス。関数型インターフェースです。
関数型インターフェイスの場合、ラムダ式を通じてインターフェイスのオブジェクトを作成できます。
package demo3;
public class lambda {
static class Ilikeimpi1 implements Ilike{
@Override
public void method() {
System.out.println("这是lambda表达式,静态内部类");
}
}
public static void main(String[] args) {
Ilikeimpi ilikeimpi=new Ilikeimpi();
ilikeimpi.method();
//调用静态内部类
Ilikeimpi1 ilikeimpi1=new Ilikeimpi1();
ilikeimpi1.method();
//局部内部类
class Ilikeimpi2 implements Ilike{
@Override
public void method() {
System.out.println("这是lambda表达式,局部内部类");
}
}
Ilikeimpi2 ilikeimpi2=new Ilikeimpi2();
ilikeimpi2.method();
//匿名内部类
Ilike ilike=new Ilike() {
@Override
public void method() {
System.out.println("这是匿名内部类");
}
};
ilike.method();
Ilike ilike2 = ()->{
System.out.println("这是lambda表达式");
};
ilike2.method();
//简化lambda表达式, 如果这里的括号带参数的话是可以直接写参数的,省略括号,只能有一行代码的情况下是可以这样简化的,如果有多行就用代码块包裹
Ilike ilike3=()->System.out.println("简化lambda表达式");
ilike3.method();
}
}
interface Ilike{
void method();
}
class Ilikeimpi implements Ilike{
@Override
public void method() {
System.out.println("这是lambda表达式");
}
}
スレッドのステータス:
スレッド方式:
- スレッドが停止しました:
package demo4;
/**
* 停止线程的方法:
* 不建议使用JDK官方提供的停止方法,比如stop,destroy
* 建议使用次数,或者设置标志位去停止。
*/
public class TestStop implements Runnable{
//在这里设置一个标志位
public boolean flag=true;
@Override
public void run() {
int i=1;
while (flag){
i++;
System.out.println(i);
System.out.println("run线程正在运行");
}
}
public void stop(){
this.flag=false;
}
public static void main(String[] args) {
TestStop testStop = new TestStop();
new Thread(testStop).start();
for (int i = 0; i < 1000; i++) {
System.out.println(i);
if (i==900){
System.out.println("线程停止了");
testStop.stop();
}
}
}
}
-
スレッドのスリープ:
ネットワーク遅延をシミュレートし、問題の発生を拡大します。
import java.text.SimpleDateFormat; import java.util.Date; /** * 模拟倒计时功能 */ public class testSleep { public static void Sleep() throws InterruptedException { int i=10; while (true){ Thread.sleep(1000); i--; if (i==0){ System.out.println("倒计时结束"); return; } System.out.println("倒计时:"+i); } } public static void main(String[] args) throws InterruptedException { // System.out.println("倒计时开始:"); // Sleep(); while (true){ Date startTime=new Date(System.currentTimeMillis()); Thread.sleep(1000); System.out.println("系统时间为:"+new SimpleDateFormat("HH:mm:ss").format(startTime)); startTime=new Date(System.currentTimeMillis()); } } }
糸のご厚意により収量:
-
現在実行中のスレッドをブロックせずに一時停止します。
-
スレッドを実行状態から準備完了状態に変換します。
-
CPU にスケジュールを変更してもらいます。礼儀正しく成功するとは限りません。 ! CPUの機嫌次第。
package demo4;
public class TestYield {
public static void main(String[] args) {
myYield myYield=new myYield();
new Thread(myYield,"A").start();
new Thread(myYield,"B").start();
}
}
class myYield implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"线程开始执行");
Thread.yield();
System.out.println(Thread.currentThread().getName()+"线程结束执行");
}
}
スレッドは結合を強制します。
スレッドキュージャンプとして理解できます
public class testJoin implements Runnable{
@Override
public void run() {
for (int i = 0; i < 200; i++) {
System.out.println("我是Vip,我要插队"+i);
}
}
public static void main(String[] args) throws InterruptedException {
testJoin testJoin=new testJoin();
Thread thread = new Thread(testJoin);
thread.start();
for (int i = 0; i < 1000; i++) {
if (i==200){
thread.join();
}
System.out.println("mian线程在执行:"+i);
}
}
}
スレッド getState のステータスを観察します。
public class testState {
public static void main(String[] args) throws InterruptedException {
Thread thread=new Thread(()->{
for (int i = 0; i < 5; i++) {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("线程结束!!!");
});
//观察状态
Thread.State state = thread.getState();
System.out.println(state);
//观察启动后
thread.start();
state = thread.getState();
System.out.println(state);
while (state!=Thread.State.TERMINATED){
//获取线程状态只要不停止就一直输出
Thread.sleep(100);
state=thread.getState();//更新线程状态
System.out.println(state);
}
}
}
スレッドが停止状態になると、再度開始することはできません。
スレッドの優先順位 優先順位:
-
スレッド スケジューラは、スレッドの優先順位に基づいて、どのスレッドを実行するかを決定します。
-
スレッドの優先度は数値 1,9 で表されます。 Thread.MIN_PRIORITY=1;
-
優先度を変更または取得するには、次のメソッドを使用します。
getPriority().setPriority(int xxx)
package demo4;
public class TestPriority {
public static void main(String[] args) {
System.out.println(Thread.currentThread().getName()+"------》"+Thread.currentThread().getPriority());
myPriority myPriority=new myPriority();
Thread thread1=new Thread(myPriority);
Thread thread2=new Thread(myPriority);
Thread thread3=new Thread(myPriority);
Thread thread4=new Thread(myPriority);
// Thread thread5=new Thread(myPriority);
// thread5.setPriority(11);
// thread5.start();
Thread thread6=new Thread(myPriority);
thread2.setPriority(5);
thread3.setPriority(3);
thread4.setPriority(1);
thread1.setPriority(Thread.MIN_PRIORITY);
thread6.setPriority(Thread.MAX_PRIORITY);
thread6.start();
thread2.start();
thread1.start();
thread4.start();
thread3.start();
}
}
class myPriority implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName()+"------》"+Thread.currentThread().getPriority());
}
}
より高いスレッドを持つものが最初に実行されるわけではありませんが、それは依然として CPU のスケジューリングに依存します。
デーモン:
-
线程分为用户线程和守护线程
-
仮想マシンは、ユーザー スレッドが実行を完了したことを確認する必要があります。
-
仮想マシンは、デーモン スレッドの実行が完了するまで待つ必要はありません。
-
たとえば、バックグラウンドで操作ログを記録し、メモリを監視し、ガベージ コレクションを待ちます。 。 。
public class Daemon {
public static void main(String[] args) {
god god=new god();
you you=new you();
Thread thread=new Thread(god);
thread.setDaemon(true); //在这里设置为守护线程
thread.start();
new Thread(you).start();
}
}
class god implements Runnable{
@Override
public void run() {
while (true){
System.out.println("上帝一直守护着你");
}
}
}
class you implements Runnable{
@Override
public void run() {
for (int i = 0; i < 35600; i++) {
System.out.println("这是我的线程,一直在运行");
}
System.out.println("我的线程运行完毕,goodbye");
}
}
彼の手術の結果は次のとおりです。
まず、ゴッドスレッドをデーモンスレッドとして設定し、私のスレッドの実行が終了すると、私が終了した後にデーモンスレッドも終了します。
スレッド同期が同期されました:
同時実行性: 同じオブジェクトが複数のスレッドによって同時に操作されます。
チケット取得イベントや銀行引き出しイベントでは、スレッド同期は実際には待機メカニズムの一種であり、複数のスレッドがこのオブジェクトにアクセスする必要があります。同時に、このオブジェクトの待機プールに入ってキューを形成し、前のスレッドがその使用を終了するまで待ちます。そして次のスレッドがそれを使用します。 。
アクセス中の同期ロック機構を追加します。スレッドがオブジェクトの排他ロックを取得して排他リソースを占有する場合、他のスレッドは使用直後にロックを解放するまで待機する必要があります。
しかし、次のような問題が発生します。
- 1 つのスレッドがロックを保持すると、このロックを必要とする他のスレッドがハングアップします。
- マルチスレッドの競合下では、ロックのロックと解放によりコンテキストの切り替えやスケジューリングの遅延が増加し、パフォーマンスの問題が発生します。
- 優先順位の高いスレッドが優先順位の低いスレッドがロックを解放するのを待つと、優先順位の逆転が発生し、パフォーマンスの問題が発生します。
注: ロックは効率に影響を与えるため、メソッド内の変更のみにロックが必要であり、読み取り専用操作には必要ありません。
synchronized キーワードを使用します。
-
メソッドにキーワードを追加する
public synchronized void buy(){}
-
synchronized 同期ブロックでは、ロックの対象は変更量であり、追加、削除、および変更操作が必要です。
プライベート二重アカウント。
同期済み(アカウント){}
CopyOnWriteArrayList:
このコレクションは安全ですが、ArrayList は安全ではありません。コレクションを安全にしたい場合は、CopyOnWriteArrayList を使用できます。
デッドロック:
同期ブロックが同時に 3 つ以上のオブジェクトのロックを保持し、同時に互いのリソースを必要とし、行き詰まりが発生すると、デッドロックの問題が発生する可能性があります。
public class DeadLock{
public static void main(String[] args) {
Makeup makeup=new Makeup("白雪公主",0);
Makeup makeup1=new Makeup("灰姑凉",1);
makeup.start();
makeup1.start();
}
}
//镜子对象
class mirror{
}
//口红对象
class lipstick{
}
class Makeup extends Thread{
//这里保证只能拿到一份对象,使用static关键字
private static mirror mirror=new mirror();
private static lipstick lipstick=new lipstick();
public String girlFriend;
public int choice;
public Makeup(String girlFriend,int choice){
this.choice=choice;
this.girlFriend=girlFriend;
}
@Override
public void run() {
try {
makeup();
} catch (InterruptedException e) {
e.printStackTrace();
}
//化妆方法
}
public void makeup() throws InterruptedException {
if (choice==0){
synchronized (mirror){
System.out.println(girlFriend+"拿到镜子的锁");
Thread.sleep(1000);
synchronized (lipstick){
System.out.println(girlFriend+"拿到口红的锁");
}
}
}else {
synchronized (lipstick){
System.out.println(girlFriend+"拿到口红的锁");
Thread.sleep(1000);
synchronized (mirror){
System.out.println(girlFriend +"拿到镜子的锁");
}}}}}
の解き方:
public void makeup() throws InterruptedException {
if (choice==0){
synchronized (mirror){
System.out.println(girlFriend+"拿到镜子的锁");
Thread.sleep(1000);
}
synchronized (lipstick){
System.out.println(girlFriend+"拿到口红的锁");
}
}else {
synchronized (lipstick){
System.out.println(girlFriend+"拿到口红的锁");
Thread.sleep(1000);
}
synchronized (mirror){
System.out.println(girlFriend +"拿到镜子的锁");
}
}
}
2 つのオブジェクトが同じロック下にないことを確認してください。
デッドロックが発生するために必要な 4 つの条件:
1.相互排他条件: リソースは一度に 1 つのプロセスのみ使用できます。
2.リクエストと保持の条件: リソースのリクエストによりプロセスがブロックされると、取得したリソースは維持されません。リソースを置きます。
3.非剥奪条件: プロセスによって取得されたリソースは、使い果たされる前に強制的に剥奪することはできません。
4.周期的待機条件: 複数のプロセスが、リソースを周期的に待機する先頭と末尾の関係を形成します。
デッドロックを回避するには、1 つ以上のそれらを破棄するだけで済みます。
ロックロック:
public class TestLock {
public static void main(String[] args) {
qiangpiao qiangpiao=new qiangpiao();
new Thread(qiangpiao).start();
new Thread(qiangpiao).start();
new Thread(qiangpiao).start();
}
}
class qiangpiao implements Runnable{
public int tiket=10;
private final ReentrantLock lock=new ReentrantLock();
@Override
public void run() {
try {
lock.lock();
while (true){
if (tiket>0){
System.out.println(tiket);
tiket--;
}else {
break;
}
}
}finally {
lock.unlock();
}
}
}
同期ロックとロックロックの比較:
ロックは明示的なロックです (ロックは手動で開閉します。ロックを閉じることを忘れないでください)。 同期は暗黙的なロックであり、範囲外になると自動的に解放されます。
Lock にはコード ブロック ロックのみがあり、同期されています。 コード ブロック ロックとメソッド ロックがあります。
Lock ロックを使用すると、JVM はスレッドのスケジュールに費やす時間が短縮され (パフォーマンスが向上します。また、スケーラビリティが向上します (より多くのサブクラスを提供します)) )
優先順位:
ロック > 同期されたコード ブロック (メソッド本体に入り、対応するリソースが割り当てられている) > 同期されたメソッド (メソッド本体外部の間)
生産者と消費者のパターン (スレッド コラボレーション):
package demo6;
public class testPC {
public static void main(String[] args) {
container container=new container();
new producer(container).start();
new customer(container).start();
}
}
//生产的食物
class chicken{
int id;
public chicken(int id) {
this.id = id;
}
@Override
public String toString() {
return "chicken{" +
"id=" + id +
'}';
}
}
//生产者
class producer extends Thread{
container container;
public producer(container container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
System.out.println("生产了"+i+"只鸡");
chicken chic=new chicken(i);
container.push(chic);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//消费者
class customer extends Thread{
container container;
public customer(container container) {
this.container = container;
}
@Override
public void run() {
for (int i = 0; i < 100; i++) {
try {
System.out.println("消费了"+container.pop().id +"只鸡");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
//缓冲区
class container{
//这里的作用是一直循环将new出来的chicken对象装入
chicken[] chickens=new chicken[10];
int count=0;
//生产鸡肉
public synchronized void push(chicken chicken) throws InterruptedException {
//如果里面满了的话就通知等待
if(count==chickens.length){
this.wait();
}else {
//往里面放入鸡肉
chickens[count]=chicken;
count++;
//这里是通知消费者消费
this.notify();
}
}
public synchronized chicken pop() throws InterruptedException {
//如果消费完了就让消费者等待
if (count == 0) {
this.wait();
}
//往里面放入鸡肉
count--;
chicken chicken1 = chickens[count];
//这里是通知消费者消费
this.notify();
return chicken1;
}
}
信号灯方式:
public class testPC1 {
public static void main(String[] args) {
TV tv=new TV();
new player(tv).start();
new watch(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){
try {
this.tv.playerMethod("快乐大本营!!!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}else{
try {
this.tv.playerMethod("抖音记录美好生活!!!");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
class watch extends Thread{
TV tv;
public watch(TV tv) {
this.tv = tv;
}
@Override
public void run() {
for (int i = 0; i < 20; i++) {
try {
tv.watchMethod();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
class TV{
String movie;
boolean flag=true;
//表演方法
public synchronized void playerMethod(String movie) throws InterruptedException {
if (!flag){
this.wait();
}
System.out.println("演员表演了:"+movie);
this.notify(); //通知观看
this.movie=movie;
this.flag=!this.flag;
}
//观看方法
public synchronized void watchMethod() throws InterruptedException {
if (flag){
this.wait();
}
System.out.println("观众观看了:"+movie);
this.notify();
this.flag=!this.flag;
}
}
スレッド プールを使用します。
背景: 同時状況のスレッドなど、特に大量の使用量で頻繁に作成および破棄されるリソースは、パフォーマンスに大きな影響を与えます。
アイデア: 事前に複数のスレッドを作成し、スレッド プールに入れ、使用時に直接取得し、使用後にスレッド プールに入れることで、生活における公共交通機関と同様に、作成と破棄の繰り返しを回避し、再利用を実現できます。
利点:
-
パフォーマンスの向上 (新しいスレッドの作成時間の短縮)
-
リソース消費量の削減
-
スレッド管理が容易になります
corePoolSize: コア プールのサイズ。
maxmumPoolSize: スレッドの最大数。
keepAliveTime: タスクがないときにスレッドが停止するまでに保持できる最大時間。
/**
* 测试线程池
*/
public class TestPool {
public static void main(String[] args) {
int i = 10;
ExecutorService service= Executors.newFixedThreadPool(i);
service.execute(new Pool());
service.execute(new Pool());
service.execute(new Pool());
service.execute(new Pool());
service.shutdown();
}
}
class Pool implements Runnable{
@Override
public void run() {
System.out.println(Thread.currentThread().getName());
}
}