先给出一个问题引入:
请编写一个多线程程序,实现两个线程,其中一个线程实现对某个成员变量每次加1操作,另外一个线程则实现对某个成员变量每次减一操作。同时,保证成员变量的值不大于1,不小于0。该成员变量的初始值为0。
要实现这个问题,显然我们需要使用多线程进行约束操作。
package Code;
public class Sample {
private int number;
public synchronized void increase()
{
if(number != 0)
{
try {
wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
number++;
System.out.println(number);
notify();
}
public synchronized void decrease()
{
if(number == 0)
{
try {
wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
number--;
System.out.println(number);
notify();
}
}
package Code;
public class IncreaseThread extends Thread {
private Sample sample;
public IncreaseThread (Sample sample)
{
this.sample = sample;
}
@Override
public void run() {
for(int i = 0; i < 20; i++)
{
try {
Thread.sleep((long)(Math.random() * 1000));
}
catch (InterruptedException e) {
e.printStackTrace();
}
sample.increase();
}
}
}
package Code;
public class DecreaseThread extends Thread {
private Sample sample;
public DecreaseThread (Sample sample)
{
this.sample = sample;
}
@Override
public void run() {
for(int i = 0; i < 20; i++)
{
try {
Thread.sleep((long)(Math.random() * 1000));
}
catch (InterruptedException e) {
e.printStackTrace();
}
sample.decrease();
}
}
}
package Code;
public class MainTest {
public static void main(String[] args) {
Sample sample = new Sample();
Thread thread1 = new IncreaseThread(sample);
Thread thread2 = new DecreaseThread(sample);
thread1.start();
thread2.start();
}
}
以上程序就实现了上述题目要求的功能。
另外如果需要加入更多的线程进行控制,为了避免唤醒混乱,我们只需要将代码改为以下即可:
while(number != 0)
{
try {
wait();
}
catch (InterruptedException e) {
e.printStackTrace();
}
}
这里总结一下多线程比较重要的知识点:
1.如果一个线程调用了某个对象的wait方法,那么该对象首先必须要拥有该对象的锁。(即wait方法处于synchronized中)
2.如果一个线程调用了某个对象的wait方法,那么该线程就会马上释放拥有该对象的锁。
3.在JAVA对象中,有两种池:锁池和等待池。
4.如果一个线程调用了某个对象的wait方法,该线程进入该对象的等待池中,并释放该对象的锁。如果之后另外一个线程调用了同一个对象的notify或notifyAll方法,则该等待池中等待的线程就会起来进入这个对象的锁池中,去等待获得该对象的锁,如果获得该对象的锁成功,该线程将会继续沿着wait之后的路径运行。
5.Sleep方法不会释放对象的锁(的拥有权)。