マルチスレッドの基本概念と実装方法

1.基本的な概念

プログラム:命令とデータの順序付けられたコレクションであり、操作上の意味はなく、静的な概念です。
プロセス:プログラムを実行する実行プロセスであり、動的な概念です。これは、システムリソース割り当ての単位です。

通常、プロセスには複数のスレッドを含めることができます。スレッドはCPUのスケジューリングと実行の単位です。
多くのマルチスレッドがシミュレートされます。実際のマルチスレッドとは、複数のCPU、つまりサーバーなどの複数のコアを指します。
マルチスレッドのシミュレーション、つまり1つのCPUの場合、CPUは同時に1つのコードしか実行できず、切り替えが速いため、同時実行されているように見えます。

スレッドは独立した実行パスです。
プログラムの実行中は、自分でスレッドを作成しなくても、バックグラウンドでメインスレッドやgcスレッドなどの複数のスレッドが存在します。main
()はメインスレッドと呼ばれ、システムの入り口であり、実行に使用されます。プログラム全体:
プロセスでは、複数のスレッドが開かれている場合、実行中のスレッドはスケジューラによってスケジュールされます。スケジューラは
オペレーティングシステムと密接に関連しており、シーケンスを人為的に妨害することはできません。
同じリソースで操作する場合、リソースの取得の問題があり、同時実行制御を追加する必要があります。
スレッドは、CPUスケジューリング時間や同時実行制御オーバーヘッドなどの追加のオーバーヘッドをもたらします。
各スレッドは独自の作業メモリで相互作用します。不適切なメモリ制御はデータの不整合を引き起こします

2.マルチスレッドを実現する3つの方法

最初のメソッド:Threadクラスを継承し、runメソッドを書き直します(理解してください)

実装コードは次のとおりです。

//创建多线程方式一:继承Thread类,重写run方法,调用start方法开启线程
public class TestThread1 extends Thread{
    
    
    @Override
    public void run(){
    
    
        for (int i = 0; i < 1000; i++) {
    
    
            System.out.println("看代码--"+i);
        }
    }

    public static void main(String[] args) {
    
    
        //main线程,主线程

        //创建线程对象,并调用start()方法启动线程
        TestThread1 thread1 = new TestThread1();
        thread1.start();

        for (int i = 0; i < 1000; i++) {
    
    
            System.out.println("学习多线程--"+i);
        }
    }
}

2番目の方法:Runnableインターフェースを実装し、runメソッドを書き直します(強調)

実装コードは次のとおりです。

//创建多线程方式二:实现Runnable接口,重写run方法,执行线程需要丢入runnable接口实现类,调用start方法
public class TestThread2 implements Runnable{
    
    
    @Override
    public void run(){
    
    
        for (int i = 0; i < 1000; i++) {
    
    
            System.out.println("看代码--"+i);
        }
    }

    public static void main(String[] args) {
    
    
        //main线程,主线程

        //创建Runnable接口的实现类对象
        TestThread2 testThread2 = new TestThread2();

        //创建线程对象,通过线程对象来开启我们的线程,代理
        Thread thread = new Thread(testThread2);
        thread.start();

        for (int i = 0; i < 1000; i++) {
    
    
            System.out.println("学习多线程--"+i);
        }
    }
}

3番目のメソッド:Callableインターフェースを実装するには(理解できる)
、Callableインターフェース実装し、戻り値の型を
書き換え、callメソッドをスローし、
ターゲットオブジェクトを
作成し、実行サービスを作成する必要があります。ExecutorService ser = Executors.newFixedThreadPool(1);
実行のために送信: Futureresult1 = ser.submit(t1);
結果を取得します:boolean r1 = result1.get()
サービスをシャットダウンします:ser.shutdownNow();

コードの練習-亀とウサギ:

//模拟龟兔赛跑
public class Race implements Runnable{
    
    

    //定义胜利者
    private static String winner;

    @Override
    public void run() {
    
    
        for (int i = 0; i <= 100; i++) {
    
    

            //模拟兔子休息。每隔10毫秒
            if (Thread.currentThread().getName().equals("兔子") && i%10==0){
    
    
                try {
    
    
                    Thread.sleep(10);
                } catch (InterruptedException e) {
    
    
                    e.printStackTrace();
                }
            }

            //判断比赛是否结束
            boolean flag = gameOver(i);
            if(flag)
                break;
            System.out.println(Thread.currentThread().getName()+"-->跑了"+i+"步");
        }
    }

    //判断是否完成比赛
    private boolean gameOver(int steps){
    
    
        if(winner != null) //已经有winner了
            return true;
        if(steps == 100){
    
    
            winner = Thread.currentThread().getName();
            System.out.println("winner is "+ winner);
            return true;
        }
        return false;
    }

    public static void main(String[] args) {
    
    
        Race race = new Race();

        new Thread(race,"兔子").start();
        new Thread(race,"乌龟").start();
    }
}

3.スレッドメソッド

setPriority(int newPriority)スレッドの優先度を変更します。
static void sleep(long millis)現在実行中のスレッドを指定されたミリ秒の間スリープ状態にします。
void join()スレッドが終了するまで待ちます。
static void yield()現在実行中のスレッドオブジェクトを一時停止し、他のスレッドを実行
void interrupt()します。スレッドを中断します。これを使用して
boolean isAlive()、スレッドがアクティブかどうかテストしないでください

テストスレッドの優先順位(priority)

複数の実行の結果によると、メインスレッドが毎回最初に実行されます。そして、他の3つはランダムに
知られています。メインスレッドの優先度は5、未設定(デフォルト)も5です。低優先度は呼び出される可能性が低いだけであり、低優先度が呼び出されないということではなく、すべてCPUスケジューリングに依存します。

コード演習:

package com.lu.state;

//测试线程优先级
//根据多次运行结果:main线程每次是都是最先运行。而另外3个,随机
//可知:main线程优先级是5,不设置(默认)也是5。优先级低只是被调用的概率低,
//并不是优先级低就不会被调用了,这都要看CPU的调度
public class TestPriority{
    
    
    public static void main(String[] args) {
    
    
        //主线程默认优先级
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());

        MyPriority myPriority = new MyPriority();
        Thread t0 = new Thread(myPriority);
        Thread t1 = new Thread(myPriority);
        Thread t2 = new Thread(myPriority);

        //先设置优先级在启动
        t1.setPriority(1);
        t2.setPriority(10);

        t1.start();
        t2.start();
        t0.start();
    }
}
class MyPriority implements Runnable{
    
    
    @Override
    public void run() {
    
    
        System.out.println(Thread.currentThread().getName()+"-->"+Thread.currentThread().getPriority());
    }
}

デーモンスレッド
スレッドは、ユーザースレッドとデーモンスレッドに分けられます。
仮想マシンは、ユーザースレッドが実行されることを確認する必要があります。
仮想マシンは、デーモンスレッドの実行を待つ必要はありません。たとえば
、バックグラウンドで操作ログを記録し、メモリを監視し、ガベージコレクションを待ちます。

コード演習:

package com.lu.state;

//测试守护线程
//上帝守护你
public class TestDaemon {
    
    
    public static void main(String[] args) {
    
    
        God god = new God();
        You you = new You();

        Thread thread = new Thread(god);
        thread.setDaemon(true);//默认是false,表示是用户线程,正常的线程都是用户线程...

        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 < 36500; i++) {
    
    
            System.out.println("你一生都开心的活着");
        }
        System.out.println("goodbye world!");
    }
}

おすすめ

転載: blog.csdn.net/qq_42524288/article/details/105783409