练手题目:
这周抽空做完了老师布置的题目 其中有一道关于线程的题目,还蛮考验人对线程的理解
题目是 开启2个线程,一个打印ABCD…XYZ,一个打印12345…26,要求A1B2C3…Z26依次打印
问题描述:
首先 ,这道题考线程机制的 ,基本烂大街了。 百度一查 答案就有N篇文章,我开始没考虑锁的问题
导致 结果没有同步输出。
原来代码如下:
package cn.edu.util;
public class Test7 {
public static void main(String[] args) {
MyThread1 thread1=new MyThread1();
thread1.start();
MyThread2 thread2=new MyThread2();
thread2.start();
}
/**
* 3、开启2个线程,一个打印ABCD...XYZ,一个打印12345...26,要求A1B2C3....Z26依次打印
*/
}
class MyThread1 extends Thread
{
@Override
public void run() {
String str="12345";
for(int i=0;i<str.length();i++)
{
synchronized (String.class)
{
// lock.notify();
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(str.charAt(i)+",");
}
}
}
}
class MyThread2 extends Thread
{
@Override
public void run() {
String str="ABCDE";
//Object lock=new Object();
for(int i=0;i<str.length();i++)
{
synchronized (String.class)
{
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.print(str.charAt(i)+",");
}
}
}
}
后来参考网上2位大佬的代码 进行了修改
大佬1:多线程:Java两个线程,一个打印A-Z,另一个打印1-26,输出结果:A1 B2 C3 … Z26
大佬2:面试题:写两个线程,一个线程打印1~26,另一个线程打印字母A-Z,交替打印数字和字母
但还是出现问题
问题代码1:
package cn.edu.util;
public class Test9 {
public static void main(String[] args) throws InterruptedException {
Object lock=new Object();
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
String str="ABCDEF";
for(int i=0;i<str.length();i++)
{
synchronized (lock)
{
try {
System.out.print(str.charAt(i));
Thread.sleep(1000);
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(" "+i+"线程1");
}
if(Thread.currentThread().isInterrupted())
{
return;
}
System.out.println("线程1执行完毕");
}
});
Thread thread2=new Thread(new Runnable() {
@Override
public void run() {
String str="123456";
for(int i=0;i<str.length();i++)
{
synchronized (lock)
{
try {
System.out.print(str.charAt(i));
Thread.sleep(1000);
lock.notify();
lock.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(" "+i+"线程2");
}
if(Thread.currentThread().isInterrupted())
{
return;
}
System.out.println("线程2执行完毕");
}
});
thread1.start();//打印字符串ABCDEF
thread2.start();//打印字符串123456
}
}
问题结果:仔细看 没多大问题 其实眼尖的同学发现问题了 就是**“线程2执行完毕”**这句话并没有打印
并且在IDEA 编译环境下还会出现 线程卡死的情况 即如图片所示 注意红色方块(就是表示程序并没结束 卡死了)
我本来计划是2个线程执行打印完字符串后 ,打印”线程XX执行完毕“结果其中一个不仅没打印出来 而且还出现程序卡死
查了好几篇关于线程中断的文章后,
文章1:Java终止线程的三种方式
文章2:java并发编程— stop() 和 interrupt() 方法的主要区别
尝试用interrupt() 函数 结果还是出问题 虽然抛出了中断异常(正常的运行结果)
测试代码如下
抛出异常后 线程还是卡死 程序还是没结束 即小方块还是红色的 注意下面图片中红色小方块
还有”线程2执行完毕“并未打印出来
原因分析:
自己问了下老师(项目经理)他说是其中一个线程在另外一个线程打印完字符串执行完毕的时候(最后的时候)并没被唤醒 所以导致锁异常 而且没必要引入中断函数
解决方案:
在打印字符串(for循环里)的时候加入判断 条件
for(int i=0;i<str.length();i++)
{
synchronized (lock)
{
try {
System.out.print(str.charAt(i));
//Thread.sleep(1000);
lock.notify();
lock.wait();
if(i==str.length()-1) //引入的判断
{
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i+"线程1");
}
同理 第二个线程里也加如这个判断 这里就不再展示了
具体代码如下
package cn.edu.util;
public class Test8 {
public static void main(String[] args) throws InterruptedException {
Object lock=new Object();
Thread thread1=new Thread(new Runnable() {
@Override
public void run() {
String str="ABCDEF";
for(int i=0;i<str.length();i++)
{
synchronized (lock)
{
try {
System.out.print(str.charAt(i));
//Thread.sleep(1000);
lock.notify();
lock.wait();
if(i==str.length()-1)
{
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i+"线程1");
}
// if(Thread.currentThread().isInterrupted())
// {
// return;
// }
System.out.println("线程1执行完毕");
}
});
Thread thread2=new Thread(new Runnable() {
@Override
public void run() {
String str="123456";
for(int i=0;i<str.length();i++)
{
synchronized (lock)
{
try {
System.out.print(str.charAt(i));
//Thread.sleep(1000);
lock.notify();
lock.wait();
if(i==str.length()-1)
{
lock.notify();
}
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println(i+"线程2");
}
// if(Thread.currentThread().isInterrupted())
// {
// return;
// }
System.out.println("线程2执行完毕");
}
});
thread1.start();//打印字符串ABCDEF
thread2.start();//打印字符串123456
}
}
最后运行结果 “线程1执行完毕” “线程2执行完毕” 均打印出来了
而且程序正常结束 注意绿色三角就是
最后
暂时先写到这里 ,各位网友如果有更加好的修改方案请留言, 我再试试改改 ,修改好代码 我再对文章进行补充修改 修改好代码
望不吝赐教