线程同步的一些问题:
首先需要分析什么情况下需要用到同步,当一个对象能够被多个线程所调用时,并且有多个语句来对这个对象进行操作,为了防止在当前线程执行语句到一半的时候,线程的控制权被交出去,让另外的线程的线程执行 ,从而导致线程安全问题,为了防止这种情况发生,同步也就因此产生,同步的目的就是把公用的对象给锁起来,当执行一次调用时,必须将锁起来的对象全部调用完,才能够将控制权交给下一个线程,这样就有效的防止了当调用对象调用到一半的时候,把控制权交出去,从而导致结果不准确。
线程同步又分为同步语句块和同步函数。同步语句块:synchronized(对象){} 锁可以使任意对象(基本数据类型除外),但是多个线程的对象必须是同一对象。同步函数:同步函数的锁对象是调用这个函数的对象。
线程通信的一些问题:
当一个对象被多个线程调用时,并且需要多个线程对该对象进行交互操作时,就需要进行线程通信,运用wait()——,notify()方法,在这里需要注意,wait和notify均需要放在同步中,并且多个线程的同步对象要相同,因为用wait方法阻塞的线程都放在一个同步对象的线程池中,而notify方法只能够唤醒同一线程池中的其他线程,假如阻塞的线程放入不同的线程池中,在某个线程池中根本无法唤醒要执行的处于另外一个线程池中的线程,并且使用wait和notify时一定要标识所属的同步的锁。
各个阻塞状态的区别:
package TestGun;
import java.util.ArrayList;
import java.util.List;
public class Gun {
List<Integer> Bullet=new ArrayList<Integer>();
public synchronized void shootBullet(int i){
if(Bullet.size()==0){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("射出一个子弹");
Bullet.remove(i);
this.notify();
}
public synchronized void addBullet(int i){
if(Bullet.size()==12){
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
System.out.println("压人第"+i+"颗子弹");
Bullet.add(i);
this.notify();
}
}package TestGun;
public class AddBullet extends Thread {
Gun aGun;
public AddBullet(Gun aGun){
this.aGun=aGun;
}
public void run(){
for(int i=0;i<13;i++){
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
aGun.addBullet(i);
}
}
}package TestGun;
public class ShootBullet extends Thread{
Gun aGun;
public ShootBullet(Gun aGun){
this.aGun=aGun;
}
public void run(){
for(int i=0;i<13;i++){
try {
sleep(10);
} catch (InterruptedException e) {
e.printStackTrace();
}
aGun.shootBullet(aGun.Bullet.size());
}
}
}
package TestGun;
public class Test {
public static void main(String[] args) {
Gun aGun =new Gun();
AddBullet add=new AddBullet(aGun);
ShootBullet shoot=new ShootBullet(aGun);
add.start();
shoot.start();
}
}