マルチスレッドと並行プログラミング【スレッドスリープ、スレッド譲歩、スレッド結合、スレッド生存判定】(2) - 徹底解説(学習のまとめ---入門から深化まで)

 

 

目次

スレッドスリープ

糸の歩留まり

ねじ結合

Thread クラスのその他の一般的なメソッド

スレッドが生きているかどうかを判断する

スレッドの優先順位


 

スレッドスリープ

 sleep() メソッド: 実行中のスレッドをスリープ時間が満杯になるまでブロック状態にし、準備完了状態にすることができます。sleep メソッドの引数は、スリープするミリ秒数です。

public class SleepThread implements Runnable
{
    @Override
    public void run() {     
        System.out.println(Thread.currentThread().getName()+" 线程开始");
    for(int i=0;i<20;i++){
              System.out.println(Thread.currentThread().getName()+" "+i);
                try {
                    //线程休眠1秒
                    Thread.sleep(1000);
               } catch(InterruptedException e) {
                    e.printStackTrace();
               }
           }
      System.out.println(Thread.currentThread().getName()+" 线程结束");
   }
    public static void main(String[] args) {
        System.out.println("主线程开始");
        Thread t = new Thread(newSleepThread());
        t.start();
        System.out.println("主线程结束");
   }
}

糸の歩留まり

 yield() は、現在実行中のスレッドを準備完了状態に戻し、同じ優先順位の他のスレッドが実行できるようにします。したがって、yield() を使用する目的は、同じ優先順位を持つスレッド間で適切なローテーションを可能にすることです。ただし、実際には、yield() がyieldの目的を達成するという保証はありません。これは、yield スレッドがスレッド スケジューラによって再度選択される可能性があるためです。

 yield メソッドを使用する場合は、次の点に注意してください。

      1 収量は静的メソッドです。

      2 yield を呼び出した後、yield は現在のスレッドに、同じ優先順位を持つスレッドに実行の機会を与えるように指示します。

      3 yield は、現在のスレッドが実行状態から準備完了状態にすぐに切り替わることを保証できません。

      4 yield は、現在のスレッドを実行状態から準備完了状態にのみ変換でき、待機状態やブロック状態には変換できません。

public class TestyieldThread implements Runnable {
    @Override
    public void run() {
        for(int i=0;i<30;i++){
            if("Thread0".equals(Thread.currentThread().getName())){
                if(i == 0){
                    Thread.yield();
               }
           }
          System.out.println(Thread.currentThread().getName()+" "+i);
       }
   }
    public static void main(String[] args) {
        Thread t1 = new Thread(newTestyieldThread());
        Thread t2 = new Thread(newTestyieldThread());
        t1.start();
        t2.start();
   }
}

ねじ結合

 現在のスレッドは、メソッドを呼び出しているスレッドを最初に実行するよう促します。メソッドを呼び出しているスレッドが実行を終了するまで、現在のスレッドは再度実行できません。スレッド A の実行中に、スレッド B の join() メソッドを呼び出して、スレッド B とスレッド A を結合できます。このように、スレッド A は、実行を続ける前に、スレッド B の実行が完了するまで待機する必要があります。

 結合メソッドの使用

join() メソッドは、このメソッドを呼び出すスレッドが run() メソッドの実行後に join メソッドの背後でコードを実行することを意味します。つまり、2 つのスレッドがマージされて同期制御が実現されます。 

class A implements Runnable{
    private Thread b;
    public A(Thread b){
        this.b = b;
   }
    @Override
    public void run() {
        for(int i=0;i<10;i++){
          System.out.println(Thread.currentThread().getName()+" A "+i);
            if(i == 5){
                try {
                    this.b.join();
               } catch(InterruptedException e) {
                    e.printStackTrace();
               }
           }
            try {
                Thread.sleep(1000);} catch (InterruptedException e){
                e.printStackTrace();
           }
       }
   }
}
class B implements Runnable{
    @Override
    public void run() {
        for(int i=0;i<20;i++){
          System.out.println(Thread.currentThread().getName()+" B "+i);
            try {
                Thread.sleep(1000);
           } catch (InterruptedException e){
                e.printStackTrace();
           }
       }
   }
}
public class TestJoinThread {
    public static void main(String[] args) {
        Thread t1 = new Thread(new B());
        Thread t = new Thread(new A(t1));
        t.start();
        t1.start();
 for(int i=0;i<10;i++){
          System.out.println(Thread.currentThread().getName()+" "+i);
            if(i ==2){
                try {
                    t.join();
               } catch(InterruptedException e) {
                    e.printStackTrace();
               }
           }
            try {
                Thread.sleep(1000);
           } catch (InterruptedException e){
                e.printStackTrace();
           }
       }
   }
}

ねじユニオンケース

要件: 父親が息子にタバコを買うように頼んでいることを理解してください。

/**
* 儿子买烟线程
*/
class SonThread implements Runnable{
    @Override
    public void run() {
        System.out.println("儿子出门买烟");
        System.out.println("儿子买烟需要10分钟");
        for(int i=0;i<10;i++){
            System.out.println("第"+i+"分钟");
            try {
                Thread.sleep(1000);
 } catch (InterruptedException e){
                e.printStackTrace();
           }
       }
        System.out.println("儿子买烟回来了");
   }
}
/**
* 爸爸抽烟线程
*/
class FatherThread implements Runnable{
    @Override
    public void run() {
        System.out.println("爸爸想抽烟,发现烟抽完了");
        System.out.println("爸爸让儿子去买一包红塔山");
        Thread t = new Thread(new SonThread());
        t.start();
        System.out.println("等待儿子买烟回来");
        try {
            t.join();
       } catch (InterruptedException e) {
            e.printStackTrace();
            System.out.println("爸爸出门找儿子");
            System.exit(1);
       }
  System.out.println("爸爸高兴的接过烟,并把零钱给了儿子");
   }
}
public class TestJoinDemo {
    public static void main(String[] args) {
        System.out.println("爸爸和儿子买烟的故事");
        Thread t = new Thread(new FatherThread());
        t.start();
   }
}

Thread クラスのその他の一般的なメソッド

現在のスレッド名を取得します

メソッド 1: this.getName() でスレッド名を取得します。このメソッドは、Thread を継承してマルチスレッドを実装するのに適しています。

class GetName1 extends Thread{
    @Override
    public void run() {
        System.out.println(this.getName());
   }
}

メソッド 2: Thread.currentThread().getName() でスレッド名を取得します。このメソッドは、マルチスレッドを実現する Runnable インターフェイスの実装に適しています。

class GetName2 implements Runnable{
    @Override
    public void run() {
      System.out.println(Thread.currentThread().getName());
   }
}

スレッドの名前を設定します

方法 1: コンストラクターを使用してスレッド名を設定します。

class SetName1 extends Thread{
    public SetName1(String name){
        super(name);
   }
    @Override
    public void run() {
        System.out.println(this.getName());
   }
}
public class SetNameThread {
    public static void main(String[] args) {
        SetName1 setName1 = new SetName1("SetName1");
        setName1.start();
   }
}

方法 2 setName() メソッドを使用してスレッド名を設定します。

class SetName2 implements Runnable{
    @Override
    public void run() {
      System.out.println(Thread.currentThread().getName());
   }
}
public class SetNameThread {
    public static void main(String[] args) {
        Thread thread = new Thread(new SetName2());
        thread.setName("SetName2");
        thread.start();
   }
}

スレッドが生きているかどうかを判断する

 isAlive() メソッド: 現在のスレッドがアクティブかどうかを判断します。アクティブ状態とは、スレッドが開始されていて終了していないことを意味します。スレッドが実行中または実行開始の準備ができている場合、スレッドは生きているとみなされます。

class Alive implements  Runnable{
    @Override
    public void run() {
        for(int i=0;i<4;i++){
          System.out.println(Thread.currentThread().getName()+" "+i);
            try {
                Thread.sleep(500);
           } catch (InterruptedException e){
                e.printStackTrace();
           }
       }
   }
}
public class TestAliveThread {
    public static void main(String[] args) {
        Thread thread = new Thread(newAlive());
        thread.setName("Alive");
        thread.start();
      System.out.println(thread.getName()+" "+thread.isAlive());
        try {
            Thread.sleep(4000);
       } catch (InterruptedException e) {
            e.printStackTrace();
       }
      System.out.println(thread.getName()+""+thread.isAlive());
   }
}

スレッドの優先順位

 スレッドの優先順位とは何ですか

各スレッドには優先順位があり、スレッドごとにスレッドの優先順位を定義できますが、これは、優先順位の高いスレッドが優先順位の低いスレッドよりも前に実行されることを保証するものではありません。スレッドの優先順位は 1 ~ 10 の数値で表され、スレッドのデフォルトの優先順位は 5 です。Java のスレッド優先度のスケジューリングはオペレーティング システムに委ねられるため、特定のオペレーティング システムの優先度に関連付けられますが、特別な必要がない場合、通常はスレッド優先度を設定する必要はありません。

知らせ

スレッドの優先度は、特定のスレッドの優先度が高く設定されている場合、どのスレッドが最初に実行されるかを意味するものではありません。つまり、処刑される可能性が高いということです。それは優先事項ではありません。

 スレッド優先度の使用

スレッド オブジェクトの優先度を取得または設定するには、次のメソッドを使用します。

1 int getPriority();

2 void setPriority(int newPriority);

注: 優先度が低いということは、単にスケジュールされる可能性が低いことを意味します。最初に優先度の高いスレッドを呼び出してから優先度の低いスレッドを呼び出すことは、必ずしも必要というわけではありません。

class Priority implements Runnable{
    private int num = 0;
    private  boolean flag = true;
    @Override
    public void run() {
        while(this.flag){
          System.out.println(Thread.currentThread().getName()+" "+num++);
       }
   }
    public void stop(){  
        this.flag = false;
   }
}
public class PriorityThread {
    public static void main(String[] args)throws Exception {
        Priority p1 = new Priority();
        Priority p2 = new Priority();
        Thread t1 = new Thread(p1,"线程1");
        Thread t2 = new Thread(p2,"线程2");
        System.out.println(t1.getPriority());
        //Thread.MAX_PRIORITY = 10
        t1.setPriority(Thread.MAX_PRIORITY);
        //Thread.MAX_PRIORITY = 1
        t2.setPriority(Thread.MIN_PRIORITY);
        t1.start();
        t2.start();
        Thread.sleep(1000);
        p1.stop();
        p2.stop();
   }
}

おすすめ

転載: blog.csdn.net/m0_58719994/article/details/131648197