3つのスレッドT 1,T 2,T 3.保証順序実行の3つの方法
19328 ワード
3つのスレッドT 1,T 2,T 3があり、どのような方法で順番に実行できるかをよく見ます。今日は手書きで試してみましたが、今まで考えていた3つの実現方法を以下に示します。
説明:ここではスレッドでsleepメソッドを使用しています。問題を発見しやすくすることを目的としています。前に他の人が書いたエラーコードを見て、何度もテストしても問題が発生しませんでした。例えば、次のようなエラー方法です。
エラーモード(最初のテストは、常に正しい出力順序であり、sleepコメント部分を放して、出力順序は直接t 3,t 2,t 1ではありません。エラーは明らかです)
public static void main(String[] args) {
final Thread t1 = new Thread(new Runnable() {
@Override
public void run() {
// try {
// Thread.sleep(100);
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
System.out.println("t1");
}
});
final Thread t2 = new Thread(new Runnable() {
@Override
public void run() {
try {
// Thread.sleep(50);
// t1 , t1
t1.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t2");
}
},"t2");
final Thread t3 = new Thread(new Runnable() {
@Override
public void run() {
try {
// Thread.sleep(10);
// t2 , t2
t2.join();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("t3");
}
});
t1.start();
t2.start();
t3.start();
正しい実現方法について説明します
1つ目の方法:スレッドにインスタンスを順番に作成します(最も考えやすい方法).
public class TestTwo {
static TestTwo t=new TestTwo();
class T1 extends Thread{
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//T1
System.out.println("T1 ")
}
}
class T2 extends Thread{
@Override
public void run() {
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
//T2
System.out.println("T2 ");
t.new T1().start();
}
}
class T3 extends Thread{
@Override
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
//T3
System.out.println("T3 ");
t.new T2().start();
}
}
public static void main(String[] args) {
t.new T3().start();
// :
//T3
//T2
///T 1スレッド実行
}
}
2つ目の方法は、単一のスレッドプール(SingleThreadExecutor)を使用して実装されているという人がいるのを見て、正確にはここはあまり一致していません.印刷結果から見ると、実は私たちは1つのスレッドの中で、3つのタスクを実行しています.
Thread t1 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " run 1");
}
}, "T1");
Thread t2 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(2000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " run 2");
}
}, "T2");
Thread t3 = new Thread(new Runnable() {
public void run() {
try {
Thread.sleep(3000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName() + " run 3");
}
}, "T3");
// ,
ExecutorService executor = Executors.newSingleThreadExecutor();
executor.submit(t3);
executor.submit(t2);
executor.submit(t1);
executor.shutdown();
// :
// pool-1-thread-1 run 3
// pool-1-thread-1 run 2
// pool-1-thread-1 run 1
第三の方式:スレッドのjoin方法を用いて実現する
joinメソッド実装原理とパラメータ説明このブログを参照すると、余分なCP作業は不要です.https://www.cnblogs.com/lcplcpjava/p/6896904.html
public class Testt {
static Testt t=new Testt();
class T1 extends Thread{
public T1(String name){
super(name);
}
@Override
public void run() {
try {
Thread.sleep(100);
} catch (InterruptedException e) {
e.printStackTrace();
}
//T3
System.out.println("T1 ");
for(int i=0;i<10;i++){
System.out.println(this.getName() + ":" + i);
}
}
}
class T2 extends Thread{
public T2(String name){
super(name);
}
@Override
public void run() {
//T3
System.out.println("T2 ");
try {
Thread.sleep(200);
} catch (InterruptedException e) {
e.printStackTrace();
}
for(int i=0;i<10;i++){
System.out.println(this.getName() + ":" + i);
}
}
}
class T3 extends Thread{
public T3(String name){
super(name);
}
@Override
public void run() {
try {
Thread.sleep(300);
} catch (InterruptedException e) {
e.printStackTrace();
}
//T3
System.out.println("T3 ");
for(int i=0;i<10;i++){
System.out.println(this.getName() + ":" + i);
}
}
}
public static void main(String[] args) {
try {
T3 t3= t.new T3("T3");
t3.start();// t3
t3.join();// , t3
T2 t2= t.new T2("T2");
t2.start();// t3
t2.join();// , t3
T1 t1= t.new T1("T1");
t1.start();// t3
t1.join();// , t3
// T3
// T3:0
// T3:1
// T3:2
// T3:3
// T3:4
// T3:5
// T3:6
// T3:7
// T3:8
// T3:9
// T2
// T2:0
// T2:1
// T2:2
// T2:3
// T2:4
// T2:5
// T2:6
// T2:7
// T2:8
// T2:9
// T1
// T1:0
// T1:1
// T1:2
// T1:3
// T1:4
// T1:5
// T1:6
// T1:7
// T1:8
// T1:9
} catch (InterruptedException e) {
e.printStackTrace();
}
}
参考ブログ:https://blog.csdn.net/yuwinter/article/details/78772933
ここのブログの書き方には間違いがあることに注意してください.ここのjoin方法は同じインスタンスに対して、そうでなければ役に立たないです.具体的には、上のリンクを参照してjoin実装原理を参照してください.
// try {
// t.new T3().start();// t3
// t.new T3().join();// , t3
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// try {
// t.new T1().start();// t1
// t.new T1().join();// , t1
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
//
// try {
// t.new T2().start();// t2
// t.new T2().join();// , t2
// } catch (InterruptedException e) {
// e.printStackTrace();
// }
以上、三つのスレッドの順番の実現方法を紹介しましたが、他のブログの乱筆の実現を見て、考えずに誤った実現を実現しました.以上、間違いがあれば、コメントを歓迎します.