Java线程学习(一):线程并发和线程忙等待

时间:2021-05-12 14:33:06

1.前序:

说到Java线程大家应该都听说过,但真正了解和熟悉线程,却并不容易。从这篇文章开始,我将以自学和实践的方式,和大家一起学习线程的内容。本篇主要讲java线程的并发和忙等待。


2.内容:

java线程最基本的两个内容在这里提一下,那就是线程的创建以及生命周期。

①java线程的创建:可以通过继承Thread类或实现Runnable接口。

②线程的生命周期:线程的创建(初始化)→调用start方法(等待cpu分配资源)→得到资源后运行run方法→阻塞(可能被sleep,wait进入阻塞状态,可通过interrupt或notify唤醒)→线程死亡(线程内程序运行完毕后)。

线程因为运行时,数据都是存在每个线程的各自的堆栈之中,而由于现在计算机的硬件结构原因,很多数据甚至是先存在线程各自CPU缓存和CPU寄存器中,所以在多个线程进行共享资源的写入问题上,就会出现所谓的线程安全问题。例如:
 

package com.jokerchen.test;/** * 线程安全问题 * @author Administrator * */public class ThreadDemo { private int count = 0; public int add() { return count++; } class ActionThread extends Thread { public ActionThread(String name) { this.setName(name); } @Override public void run() { // TODO Auto-generated method stub int num = add(); System.out.println("当前线程为:"+Thread.currentThread().getName()+",现在count等于:"+count); } } public static void main(String[] args) { ThreadDemo threadDemo = new ThreadDemo(); ActionThread at_one = threadDemo.new ActionThread("AA"); ActionThread at_two = threadDemo.new ActionThread("BB"); at_one.start(); at_two.start(); } }
(这里偷个懒,直接用的内部类来创建的线程类对象)结果为:

Java线程学习(一):线程并发和线程忙等待Java线程学习(一):线程并发和线程忙等待

很奇怪,这里出现了两种结果对不对。而这里就是因为线程数据的存储问题,因其中一个线程的改写数据,没有及时更新到主存中,导致其他的线程也没有识别更新后的数据。
在说说并发和并行。个人理解:并发就是指多个线程在一时间段内通过cup资源的分配切换来运行;而并行则是指多个线程在同一时刻同时运行。就比如最经典的卖票实例:
package com.jokerchen.test;

public class ThreadTest {

class Ticket implements Runnable
{
public int num = 100;
@Override
public void run() {
// TODO Auto-generated method stub
while(num > 0){
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
num--;
System.out.println("当前线程为:"+Thread.currentThread().getName()+",目前所剩票数为:"+num);
}

}

}

public static void main(String[] args) {
Ticket tt = new ThreadTest().new Ticket();
new Thread(tt,"AA").start();
new Thread(tt,"BB").start();

}

}
结果如下:
Java线程学习(一):线程并发和线程忙等待
Java线程学习(一):线程并发和线程忙等待
大家也能看到,出现了同号票和负数票。这就是在线程切换时所产生的并发问题。这是因为在线程切换期间,因为票数做减法操作时,还没来及的判断和打印,另外的线程就已经运行了。那么此时我们需要加入同步块来解决这种情况:
class Ticket implements Runnable
{
public int num = 100;
@Override
public void run() {
// TODO Auto-generated method stub
while(true){
try {
Thread.currentThread().sleep(10);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
synchronized (this) {
num--;
if(num < 0) break;
System.out.println("当前线程为:"+Thread.currentThread().getName()+",目前所剩票数为:"+num);
}

}

}

}
那么此时的重票和负票情况,就得以解决了,结果如下:
Java线程学习(一):线程并发和线程忙等待

再来谈下线程的忙等待情形。忙等待即是一个线程在等待另外一个线程所给出的信号,而这个信号必然是在一个共享对象中存在的,这样才能达到多线程的信息共享。当等到信号之后才会进行下一步运行的情况。当然,这里也就涉及到了另外一种情况,如果一直等不到呢,那么就会进入我们常说的 死锁 状态。下面来看一下我所写的忙等待实例:
实体类(共享对象)代码
package com.jokerchen.test;

public class MyProcess {

private boolean flag = false;

public synchronized boolean getProcess()
{
return this.flag;
}

public synchronized void setProcess(boolean bool)
{
this.flag = bool;
}

}
实现类
package com.jokerchen.test;

public class BusyWait {


/**
* 忙等待
*/
public static void main(String[] args) {
//实例共享对象
final MyProcess mp = new MyProcess();
Thread thread1 = new Thread("AA"){
@Override
public void run() {
// TODO Auto-generated method stub

try {
//睡眠五秒
Thread.currentThread().sleep(5000);
mp.setProcess(true);
System.out.println("当前线程为:"+Thread.currentThread().getName()+",并已设置共享对象信号属性flag为true!");
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
};

Thread thread2 = new Thread("BB")
{
@Override
public void run() {
// TODO Auto-generated method stub
//等待其他线程的信号
while (true) {
//睡眠1秒
try {
Thread.currentThread().sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
if(mp.getProcess())
{
System.out.println("当前线程为:"+Thread.currentThread().getName()+",已经获得其他线程的信号!");
break;
}
else
{
System.out.println("当前线程为:"+Thread.currentThread().getName()+",正在等待其他线程的信号......");
}
}
}
};

//开始忙等待....
thread1.start();
thread2.start();
}

}
运行结果如下:
Java线程学习(一):线程并发和线程忙等待

3.总结

多线程使用起来,有时候能简化我们的运行程序。当然,在多数情况下,还是比单体运行程序要复杂一些,所以需要注意很多问题。因博主也是刚开始深入学习和熟悉多线程,所以文章中可能有不足或者有太正确的观点,希望大家在借鉴之时也能提出宝贵的意见,让我们一起学习一起进步。。