Java多线程学习--03

说明:参考《Java多线程核心技术》

7、线程的优先级

源码:

 public final void setPriority(int newPriority) {
   		// this thread's thread group.
        ThreadGroup g;
  	    // if the current thread is allowed to  access this thread
        checkAccess();
        if (newPriority > 10 || newPriority < 1) {
            throw new IllegalArgumentException();
        }
        if((g = getThreadGroup()) != null) {
            if (newPriority > g.getMaxPriority()) {
                newPriority = g.getMaxPriority();
            }
            setPriority0(priority = newPriority);
        }
    }

如果线程A启动线程B,那么线程A和线程B的优先级相同。

默认的线程优先级为5,最大为10,最小为1.

高优先级的线程总是大部分先执行完,但是不代表高优先级的的线程总是先全部执行完。当线程优先级等级差别较大的时候,谁先执行和代码的调用顺序是无关的。优先级高的线程不一定每一次都先执行完,优先级的执行具有随机性。可以通过设置线程的优先级,来尽量让想要先执行的线程先执行。

8、守护线程(Daemon)

Java中的线程有两种,一种为用户线程,另一种为守护线程,守护线程是一种特殊的线程,当进程中不存在非守护线程时,则守护线程自行销毁。最典型的守护线程就是垃圾回收线程。

2、对象及变量的访问

1、实例变量的非线程安全

如果多个线程共同访问一个对象的实例变量,那么可能出现线程不安全的问题。

public class UnSafeThreadA extends Thread{
    private PrivateNum num;
    public UnSafeThreadA(PrivateNum num) {
        super();
        this.num = num;
    }
    @Override
    public void run(){
        super.run();
        num.addI("a");
    }
}
public class UnSafeThreadB extends Thread {
    private PrivateNum num;
    public UnSafeThreadB(PrivateNum num) {
        super();
        this.num = num;
    }
    @Override
    public void run(){
        super.run();
        num.addI("b");
    }
}
public class PrivateNum {
    private int num = 0;
    public void addI(String userName) {
        try {
            if (userName.equals("a")){
                num = 100;
                System.out.println("a is right");
                Thread.sleep(1000);
            } else {
                num = 200;
                System.out.println(userName + "---" + "num = " + num);
            }
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class UnSafeThreadTest {
    public static void main(String[] args) {
      // 共同访问实体变量
        PrivateNum privateNum = new PrivateNum();
        UnSafeThreadA threadA = new UnSafeThreadA(privateNum);
        threadA.start();
        UnSafeThreadB threadB = new UnSafeThreadB(privateNum);
        threadB.start();
    }
}
/**
a is right        
b is right
b---num = 200
a---num = 200
 */

原因在于:ThreadA 在执行期间,由于sleep()方法使得ThreadB有机会去占用CPU的time slice。在sleep()方法结束之前,ThreadB已经执行结束了。通过缩小sleep方法的参数,让程序可能出现想要的结果。

正确的解决办法是在addI()方法前加synchronized关键字。

2、多个对象多个锁

多个对象多个锁的话,很可能产生线程安全地问题

public class PrivateNum {
    private int num = 0;
  // add synchronized
  synchronized  public void addI(String userName) {
        try {
            if (userName.equals("a")){
                num = 100;
                System.out.println("a is right");
                Thread.sleep(1000);
            } else {
                num = 200;
                System.out.println("b is right");
            }
            System.out.println(userName + "---" + "num = " + num);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
}
public class MultiObjectTest {
    public static void main(String[] args) {
        // two  different Object
        PrivateNum numA = new PrivateNum();
        PrivateNum numB = new PrivateNum();
        UnSafeThreadA threadA = new UnSafeThreadA(numA);
        threadA.start();
        UnSafeThreadB threadB = new UnSafeThreadB(numB);
        threadB.start();
    }
}
/**
 * a is right
 b is right
 b---num = 200
 a---num = 100
 */

关键字synchronized取得的锁都是对象锁,而不是把一段代码或者方法当做锁,所以哪个线程先执行带有synchronized关键字的方法,哪个线程就持有方法所属对象的锁,其他的线程就处于堵塞状态。

3、synchronized和asynchronized

线程A先获得object对象的锁,但是线程B可以通过异步的方式调用object对象的非synchronized修饰的方法。

线程A先获得object对象的锁,如果线程B此时向调用object对象中的synchronized方法,则必须等待。

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值