前言
学了几天的多线程基础部分,书上的东西一看就懂,但是真的实践还是值得推敲的
题目
1、写一个程序,线程C在线程B后执行,线程B在线程A之后进行
package thread;
public class Test {
public static void main(String[] args) {
Thread threadA = new Thread(new Runnable() {
@Override
public void run() {
System.out.println("This is A");
}
});
Thread threadB = new Thread(() -> {
try {
threadA.join();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("This is B");
});
Thread threadC = new Thread(new Runnable() {
@Override
public void run() {
try {
threadB.join();
} catch (Exception e) {
// TODO: handle exception
}
System.out.println("This is C");
}
});
threadA.start();
threadB.start();
threadC.start();
}
}
或者这样
package thread;
public class Test2 {
public static void main(String[] args) {
Thread aThread = new Thread(() -> {
System.out.println("This is A");
});
Thread bThread = new Thread(() -> {
System.out.println("This is B");
});
Thread cThread = new Thread(() -> {
System.out.println("This is C");
});
try {
aThread.start();
aThread.join();
bThread.start();
bThread.join();
cThread.start();
cThread.join();
} catch (Exception e) {
// TODO: handle exception
}
}
}
2、编写一个程序,开启3个线程,这3个线程的ID分别为A、B、C,每个线程将自己的ID在屏幕上打印10遍,要求输出结果必须按ABC的顺序显示;如:ABCABC….依次递推。
第一次代码
package thread;
public class Test4 {
public static void main(String[] args) {
Thread threadA = new Thread(() -> {
System.out.println("This is A");
});
Thread threadB = new Thread(() -> {
try {
threadA.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("This is B");
});
Thread threadC = new Thread(() -> {
try {
threadB.join();
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
System.out.println("This is C");
});
for (int i=0;i<10;i++) {
threadA.start();
threadB.start();
threadC.start();
try {
Thread.sleep(300);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
---output----
This is A
This is B
This is C
Exception in thread "main" java.lang.IllegalThreadStateException
at java.base/java.lang.Thread.start(Thread.java:804)
at thread.Test4.main(Test4.java:30)
分析:
一开始我以为是执行地太快了,在main里面sleep了一会,结果发现还是崩了,最后google才发现,原来同样的线程不能循环执行,这和线程的生命周期有关系。销毁了之后就不能再进行了。
第二次代码
package thread;
public class Test3 {
public static void main(String[] args) {
for (int i = 0; i < 10; i++) {
Thread threadA = new Thread(() -> {
System.out.println(Thread.currentThread().getName());
}, "A");
Thread threadB = new Thread(() -> {
try {
threadA.join();
System.out.println(Thread.currentThread().getName());
} catch (Exception e) {
// TODO: handle exception
}
}, "B");
Thread threadC = new Thread(() -> {
try {
threadB.join();
System.out.println(Thread.currentThread().getName());
} catch (Exception e) {
// TODO: handle exception
}
}, "C");
threadC.start();
threadB.start();
threadA.start();
try {
Thread.sleep(300);
} catch (Exception e) {
// TODO: handle exception
}
}
}
}
分析:
这里的sleep比较重要,因为每次都new了一个线程,主线程执行地太快,会导致新的线程先于旧线程的顺序执行。类似于插队了。但是我觉得这里new了多个线程不太好,为什么不用3个线程直接完成呢?好像不符合题目的开启3个线程这个条件
第三次代码
package thread;
public class Test {
public static class Worker {
Object lock = new Object();
int flag = 1;
public void PrintA() {
synchronized (lock) {
while (flag != 1) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO: handle exception
}
}
flag = 2;
lock.notifyAll();
System.out.println(Thread.currentThread().getName());
}
}
public void PrintB() {
synchronized (lock) {
while (flag != 2) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO: handle exception
}
}
flag = 3;
lock.notifyAll();
System.out.println(Thread.currentThread().getName());
}
}
public void PrintC() {
synchronized (lock) {
while (flag != 3) {
try {
lock.wait();
} catch (InterruptedException e) {
// TODO: handle exception
}
}
flag = 1;
lock.notifyAll();
System.out.println(Thread.currentThread().getName());
}
}
}
public static void main(String[] args) {
Worker worker = new Worker();
Thread threadA = new Thread(() -> {
for (int i = 0; i < 10; i++) {
worker.PrintA();
}
}, "A");
Thread threadB = new Thread(() -> {
for (int i = 0; i < 10; i++) {
worker.PrintB();
}
}, "B");
Thread threadC = new Thread(() -> {
for (int i = 0; i < 10; i++) {
worker.PrintC();
}
}, "C");
threadA.start();
threadB.start();
threadC.start();
}
}