多线程(四)————线程方法和线程同步

线程的优先级

  • 线程的优先级有1-10十级,数值越高优先级越高(超出范围会抛出异常)
  • getPriority()和setPriority(int)分别用来获取和设置线程的优先级
  • 优先级高只是增加对应线程被cpu调度执行的概率,并不代表该线程会一直比优先级低的线程先执行
  • **注意:**线程设置优先级建议在线程启动之前
public class Test1 implements Runnable {
    @Override
    public void run() {
        System.out.println(Thread.currentThread().getName()+"---->"+Thread.currentThread().getPriority());
    }

    public static void main(String[] args) {
        System.out.println(Thread.currentThread().getPriority());

        Test1 t=new Test1();
        Thread t1=new Thread(t,"1");
        Thread t2=new Thread(t,"2");
        Thread t3=new Thread(t,"3");
        Thread t4=new Thread(t,"4");
        Thread t5=new Thread(t,"5");
        Thread t6=new Thread(t,"6");
        //设置优先级
        t1.setPriority(1);
        t2.setPriority(3);
        t4.setPriority(6);
        t5.setPriority(8);
        t6.setPriority(10);
        //启动线程
        t1.start();
        t2.start();
        t3.start();
        t4.start();
        t5.start();
        t6.start();
    }
}

守护线程

  • 线程分为用户线程和守护线程
  • java虚拟机必须确保用户线程执行完毕而不用等待守护线程
  • 守护线程作用:记录日志、监控内存、垃圾回收等等
  • setDaemon(true)方法把线程设置为守护线程
public class Test2 {
    public static void main(String[] args) {
        De de=new De();
        User user=new User();
        //守护线程
        Thread thread=new Thread(de);
        //把线程设置为守护线程
        thread.setDaemon(true);
        thread.start();
        //用户线程
        new Thread(user).start();
    }
}
//守护线程
class De implements Runnable{
    @Override
    public void run() {
        while (true){
            System.out.println("defender running");
        }
    }
}

//用户线程
class User implements Runnable{
    @Override
    public void run() {
        for (int i = 0; i < 100; i++) {
            System.out.println("User running");
        }
    }
}


可以看到,即使守护线程写成while true死循环,也会在用户线程执行完毕后自动退出

线程同步

  • 使用多线程时,若多个线程访问同一个对象,尤其是对对象进行修改操作时,就需要引入线程同步。多个线程需要访问同一对象时,进入该线程的等待池,只有当前面线程访问结束,后面的线程才能够访问到该对象。
  • 主要引入锁和队列的概念:队列即排队,线程访问对象应该有先后顺序;锁即在线程访问对象在对对象进行操作之前,给对象上锁即可防止其他线程对对象进行访问操作。
  • 同步方法
    • 使用synchronized关键字对代码块或者方法进行修饰,即可控制对每一个对象的访问,每一个对象都对应一把锁,只有获得锁的方法可以对对象进行访问操作,没有获得锁的线程将会被阻塞,等待直到占用锁的线程施放锁。
    • 注意:使用synchronized声明一个大的代码块将会影响代码的执行效率。
    • 多个线程对多个对象同时操作时,有可能会造成死锁的情况
  1. 可以使用synchronized关键字直接修饰方法,此时默认锁的对象为“this”
  2. 也可以使用synchronized(Object obj){代码块} 的形式,其中obj为被锁的对象。

死锁测试:

public class Test4 {
    public static void main(String[] args) {
        Lock lock= new Lock();
        new Thread(lock,"1").start();
        new Thread(lock,"2").start();
    }
}
class Lock implements Runnable{
    //两个被访问的对象
    private int num1=1,num2=2;
    //synchronized void lock(int num){
    void lock(int num){
        System.out.println("线程"+Thread.currentThread().getName()+"成功锁num"+num);
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
    }
    @Override
    public void run() {
        if (Thread.currentThread().getName().equals("1")){
            //如果是线程1 先锁1再锁2
            System.out.println("线程"+Thread.currentThread().getName()+"尝试锁num1");
            synchronized ((Object) num1){
                lock(num1);
                System.out.println("线程"+Thread.currentThread().getName()+"尝试锁num2");
                synchronized ((Object) num2){
                    lock(num2);
                }
            }
        }else{
            //如果是线程2,先锁2再锁1
            System.out.println("线程"+Thread.currentThread().getName()+"尝试锁num2");
            synchronized ((Object) num2){
                lock(num2);
                System.out.println("线程"+Thread.currentThread().getName()+"尝试锁num1");
                synchronized ((Object) num1){
                    lock(num1);
                }
            }
        }
    }
}

  • 可以看到出现了死锁现象
  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值