线程基础知识

本文详细介绍了Java线程的常用方法,包括设置和获取线程名、优先级、启动、中断等。还讨论了线程的礼让(yield)、插队(join)以及用户线程和守护线程的概念。同时,分析了线程的生命周期和状态转换,并通过示例展示了线程同步机制,如synchronized关键字的使用,以及如何避免死锁。最后,提到了线程锁的释放条件和线程安全问题。
摘要由CSDN通过智能技术生成

线程常用方法第一组

1.setName //设置线程名称,使之与参数 name相同
2.getName //返回该线程的名称
3.strat //使该线程开始执行;java虚拟机底层调用该线程的 start0 方法
4.run //调用线程对象 run方法;
5.setpriority //更改线程的优先级
6.getpriority //获取线程的优先级
7.sleep //在指定的毫秒数内让当前正在执行的线程休眠(暂停执行)
8.interrup //中断线程

package hsp.tanke.method;

public class ThreadMethod {
    public static void main(String[] args) throws InterruptedException {
        T t = new T();
        t.setName("killer");
        t.setPriority(Thread.MIN_PRIORITY);
        t.start();

        //主线程打印5次 Hi ,然后我就中断 子线程的休眠.
        for (int i = 0; i <5 ; i++) {
            Thread.sleep(1000);
            System.out.println("hi"+i);
        }

        //
        System.out.println(Thread.currentThread().getName() + "的优先级 = " + t.getPriority());

        t.interrupt();//中断 t线程的休眠
    }
}

class T extends Thread{
    @Override
    public void run() {
        while (true){
            for (int i = 0; i <100 ; i++) {
                System.out.println(Thread.currentThread().getName() + "吃包子"+i);
            }
            try {
                sleep(20*1000);
            } catch (InterruptedException e) {
                System.out.println(Thread.currentThread().getName() +"被interrupt中断了");
            }
        }
    }
}

线程常用方法第二组

1.yield:线程的礼让。让出cpu,让其他线程执行,但礼让的时间不确定,所以也不一定礼让成功
2.join:线程的插队。插队的线程一旦插队成功,则肯定先执行完插入的线程的任务


用户线程和守护线程

1.用户线程:也叫工作线程,当线程的任务执行完或通知方式结束
2.守护线程:一般是为工作线程服务的,当所有的用户线程结束,守护线程自动结束

3.常见的守护线程:垃圾回收机制

package hsp.tanke.method;

public class ThreadMethod03 {
    public static void main(String[] args) throws InterruptedException {

        MyDeamonThread myDeamonThread = new MyDeamonThread();
        //如果我们希望当main线程结束后,子线程自动结束
        //只需将子线程设为守护线程即可
        myDeamonThread.setDaemon(true);
        myDeamonThread.start();
        for (int i = 0; i <10 ; i++) {//main线程
            System.out.println("强还在工作...");
            Thread.sleep(1000);
        }
    }
}

class MyDeamonThread extends Thread{

    @Override
    public void run() {
        while (true){
            try {
                Thread.sleep(1000);//休眠1000毫秒
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
            System.out.println("宋和马还在说话...");
        }
    }
}

线程的生命周期

线程状态

  • NEW
    尚未启动的线程处于此状态
  • RUNNABLE
    在Java虚拟机中执行的线程处于此状态,此状态可再分为 Ready 和 Running 状态
  • BLOCKED
    被阻塞等待监视器锁定的线程处于此状态
  • WAITING
    正在等待另一个线程执行特定动作的线程处于此状态
  • TIMED_WAITING
    正在等待另一个线程执行动作达到指定等待时间的线程处于此状态
  • TERMINATED
    已退出的线程处于此状态

线程状态转换图

在这里插入图片描述

package hsp.tanke.method;

public class ThreadState {
    public static void main(String[] args) throws InterruptedException {

        T4 t4 = new T4();

        System.out.println(t4.getName() + "的状态 " + t4.getState());
        t4.start();

        while (Thread.State.TERMINATED != t4.getState()){
            System.out.println(t4.getName() + "的状态 " + t4.getState());
            Thread.sleep(500);
        }

        System.out.println(t4.getName() + "的状态 " + t4.getState());
    }
}

class T4 extends Thread{
    @Override
    public void run() {
        while (true){
            for (int i = 0; i <10; i++) {
                System.out.println("hi" + i);
                try {
                    sleep(1000);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            break;
        }
    }
}

Synchronized

线程同步机制

1.在多线程编程,一些敏感数据不允许被多个线程同时访问,此时就使用同步访问技术,保证数据在任何时刻,最多有一个线程访问,以保证数据的完整性
2.也可以这样理解:线程同步,即当有一个线程在对内存进行操作时,其他线程都不可以对这个内存地址进行操作,直到该线程完成操作,其他线程才能对该内存地址进行操作

同步具体方法-Synchronized

1.同步代码块
synchronized(对象){//得到对象的锁,才能操作同步代码
//需要被同步代码
}
2.synchonized还可以放在方法声明中,表示整个方法-为同步方法
public synchronized void m (String name){
//需要被同步代码
}

互斥锁

1.Java语言中,引入了对象互斥锁的概念,来保证共享数据操作的完整性。
2.每个对象都对应于一个可称为 “互斥锁” 的标记,这个标记用来保证在任一时刻,只能由一个线程访问该对象。
3.关键字synchronized 来与对象的互斥锁联系。当某个对象用synchronized修饰时,表明该对象在任一时刻只能由一个线程访问
4.同步的局限性:导致程序的执行效率要降低
5.同步方法(非静态)的锁可以是this,也可以是其他对象(要求是同一个对象)
6.同步方法(静态)的锁为当前类本身。

public class SellTicket {
    public static void main(String[] args) {
    
       // SelectTicket02 selectTicket1 = new SelectTicket02();
       //SelectTicket02 selectTicket2 = new SelectTicket02();
       //SelectTicket02 selectTicket3 = new SelectTicket02();
       //selectTicket1.start();//开启线程
       //selectTicket2.start();//开启线程
       //selectTicket3.start();//开启线程

        SelectTicket03 selectTicket01 = new SelectTicket03();
        Thread t1 = new Thread(selectTicket01);
        Thread t2 = new Thread(selectTicket01);
        Thread t3 = new Thread(selectTicket01);
        t1.start();
        t2.start();
        t3.start();

    }
}

class SelectTicket02 extends Thread {
    private int ticketNum = 100;//卖100张票
    private  boolean loop = true;
    
	//1. public synchronized static void m1(){} 锁是加在 SelectTicket02.class
	//2.如果在静态方法中,实现一个同步代码块
	/*
		synchronized(SelectTicket02.class){
			 System.out.println("m2")
		}
	*/
	public synchronized static void m1(){
	 System.out.println("m2")
	}
	
    //1. public synchronized void sell(){} 就是一个同步方法
    //2.这时锁在 this对象
    //3.也可以在代码块上写 synchronized 同步代码块
    public synchronized void sell() {//同步方法,在同一时刻, 只能有一个线程来执行sell方法
        if (ticketNum <= 0){
            System.out.println("售票结束...");
            loop = false;
            return;
        }
        
        //线程休眠100毫秒
        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        
        System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + "剩余票数" + (--ticketNum));
        }


    @Override
    public void run() {
        while (loop){
            sell();
        }
    }
}

class SelectTicket03 implements Runnable {//3.同步代码块  互斥锁还是在this对象
    private int ticketNum = 100;
    private  boolean loop = true;
    Object object = new Object();
    
    public  void m() {
        synchronized(/*this*/object){
        if (ticketNum <= 0){
            System.out.println("售票结束...");
            loop = false;
            return;
        }

        try {
            Thread.sleep(100);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
        System.out.println("窗口" + Thread.currentThread().getName() + "售出一张票" + "剩余票数" + (--ticketNum));
        }
    }

    @Override
    public void run() {
        while (loop){
            m();
        }

    }
}

死锁

  • 多个线程都占用了对方的锁资源,但不肯相让,导致了死锁,在编程是一定要避免死锁的发生

  • 案例
    妈妈:你先完成作业,才让你玩手机
    小明:你先让我玩手机,我才完成作业

package hsp.tanke.DeadLock;

public class DeadLock {
    public static void main(String[] args) {
        DeadLockDemo A = new DeadLockDemo(true);
        DeadLockDemo B = new DeadLockDemo(false);
        A.setName("A");
        B.setName("B");
        A.start();
        B.start();

    }
}

class DeadLockDemo extends Thread{
    static Object o1 = new Object();//保证多线程, 共享一个对象,这里使用static
    static Object o2 = new Object();
    boolean flag;

    public DeadLockDemo(boolean flag){//构造器
        this.flag = flag;
    }

    @Override
    public void run() {

        //业务逻辑分析
        //1.如果 flag 为 T,线程A 就会先得到/持有 o1 对象锁,然后尝试去获取 o2 对象锁
        //2.如果线程A 得不到 o2 对象锁,就会Blocked
        //3.如果 flag 为 F,线程B 就会先得到/持有 o2 对象锁,然后尝试去获取 o1 对象锁
        //4.如果线程B 得不到 o1 对象锁,就会Blocked
        if (flag){
            synchronized (o1){
            System.out.println(Thread.currentThread().getName() + "进入1");
            synchronized (o2){
            System.out.println(Thread.currentThread().getName() + "进入2");
                }
            }
        }else {

                synchronized (o2){
                    System.out.println(Thread.currentThread().getName() + "进入2");
                    synchronized (o1){
                        System.out.println(Thread.currentThread().getName() + "进入1");
                }
            }
        }
    }
}

释放锁

  • 下面操作释放锁
    1.当前线程的同步方法、同步代码块执行结束
    案例:上厕所,完事出来
    2.当前线程在同步代码块,同步方法中遇到break、return。
    案例:没有正常的完事,经理叫他修改bug,不得已出来
    3.当前线程在同步代码块、同步方法中出现了未处理的Error或Exception,导致异常结束
    案例:没有正常的完事,发现忘带纸,不得已出来
    4.当前线程在同步代码块、同步方法中执行了线程对象的wait()方法,当前线程暂停,并释放锁
    案例:没有正常完事,觉得需要酝酿下,所以出来等会再进去
  • 下面操作不会释放锁
    1.线程执行同步代码块或同步方法时,程序调用Thread.sleep()、Thread.yield()方法暂停当前线程的执行,不会释放锁
    2.线程执行同步代码块时,其他线程调用了该线程的suspend()方法将该线程挂起,该线程不会释放锁。
    提示:应尽量避免使用suspend()和resume()来控制线程,方法不再推荐使用

观看韩顺平老师讲解线程视频的笔记
地址:https://www.bilibili.com/video/BV1Ay4y1t7hz

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值