线程笔记

同步锁

  • 保证数据操作的完整性
  • 每个对象对应一个锁的标记,保证在任一时刻,只能有一个线程访问该对象
  • 用synchronized修饰符来与对象的同步锁联系
  • 加同步锁会导致程序的执行效率降低
  • 非静态同步方法的锁为this(当前对象),静态同步方法的锁为当前类本身

创建线程的方式

  1. 实现Runnable接口
public class test_03{
    public static void main(String[] args) {
        ThreadTest test = new ThreadTest();
        Thread t = new Thread(test);
        t.start();
    }
}

class ThreadTest implements Runnable{

<span class="hljs-meta">@Override
<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-keyword">void <span class="hljs-title">run<span class="hljs-params">() {
    System.out.println(<span class="hljs-string">"创建了一个线程:"+Thread.currentThread().getName());
}

}

2. 继承Thread类

public class test_03{
    public static void main(String[] args) {
        ThreadTest test = new ThreadTest();
        test.start();
    }
}

class ThreadTest extends Thread{
@Override
public void run() {
System.out.println("创建了一个线程:"+Thread.currentThread().getName());
}
}

推荐使用实现Runnable接口的方式来创建线程,原因如下

  • 不需要重写Thread类的方法
  • 可以弥补java单继承的机制
  • 多个线程可以共享一个Runnable实例对象
  • 使用接口更灵活

线程常用的方法

  1. setName -> 设置线程名
  2. getName -> 返回线程名
  3. start -> 执行线程
  4. run -> 线程对象的主方法,(是一个普通方法,直接调用不会创建线程)
  5. setPriority -> 更改线程的优先级
  6. getPriority -> 获取线程的优先级
  7. sleep -> 休眠、暂停执行 (毫秒)
  8. interrupt -> 中断线程,(如果一个线程处于了阻塞状态,则会抛出InterruptedException异常,为了让线程从阻塞状态醒来,并且在结束线程前让程序员有足够的时间来处理中断请求)
  9. yield -> 线程礼让,礼让的时间不确定,不一定会礼让成功(资源紧张时成功的概率高,由CPU决定)
  10. join -> 让其他线程插队,执行完插队的线程任务,再继续执行当前线程

举例

public class test_02 {
    public static void main(String[] args) {
        ThreadDemo demo = new ThreadDemo();
        Thread t = new Thread(demo);
        t.setName("凣凣");
        //设置优先级为1 默认为5 最大为10
        t.setPriority(Thread.MIN_PRIORITY);
        t.start();
        Thread.currentThread().setName("主线程");
        for (int i = 1; i<=5;i++){
            System.out.println(Thread.currentThread().getName() + "吃饭中...");
            try {
                //休眠0.5秒
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
        //中断线程
        t.interrupt();
    }
}

class ThreadDemo implements Runnable{
@Override
public void run() {
while (true){
System.out.println(Thread.currentThread().getName() + "等吃完饭去睡觉...");
try {
//休眠20秒
Thread.sleep(20000);
} catch (InterruptedException e) {
System.out.println(Thread.currentThread().getName() + "吃完饭了,我要去睡觉zzZ");
return;
}
}
}
}

java基础——线程笔记

打印执行结果

线程分类

  • 用户线程:也叫工作线程,当线程任务执行完或以通知方式结束
  • 守护线程:可以理解为为工作线程服务的线程,当所有的用户线程结束,守护线程自动结束
public class test_02 {
    public static void main(String[] args) {
        ThreadDemo demo = new ThreadDemo();
        Thread t = new Thread(demo);
        //调用Thread对象的setDaemon(true)将线程设为守护线程
        t.setDaemon(true);
        t.start();
        for (int i = 1; i<=10;i++){
            System.out.println("吃饭中...");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }
        }
    }
}

class ThreadDemo implements Runnable{
@Override
public void run() {
while (true){
System.out.println("等吃完饭去睡觉...");
try {
Thread.sleep(500);
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}

  • 执行结果
java基础——线程笔记

打印执行结果

死锁

  • 多个线程占用了对方的锁资源无法释放导致死锁

示例

//模拟线程死锁
public class test_01 {
    public static void main(String[] args) throws IOException, InterruptedException {
        Thread t1 = new Thread(new LockDemo(true));
        Thread t2 = new Thread(new LockDemo(false));
        t1.setName("第一个线程");
        t2.setName("第二个线程");
        t1.start();
        t2.start();
    }
}

class LockDemo implements Runnable{
static Object o1 = new Object();
static Object o2 = new Object();
boolean flag;

<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-title">LockDemo<span class="hljs-params">(<span class="hljs-keyword">boolean flag){
    <span class="hljs-keyword">this.flag = flag;
}

<span class="hljs-comment">//死锁
<span class="hljs-function"><span class="hljs-keyword">public <span class="hljs-keyword">void <span class="hljs-title">run<span class="hljs-params">(){
    <span class="hljs-keyword">if(flag){
        <span class="hljs-comment">//第一个线程会拿到o1的锁
        <span class="hljs-keyword">synchronized (o1){
            System.out.println(Thread.currentThread().getName()+<span class="hljs-string">"得到锁1");
            <span class="hljs-comment">//当想去拿o2的锁时,拿不到,因为已经被第二个线程占用
            <span class="hljs-keyword">synchronized (o2){
                System.out.println(Thread.currentThread().getName()+<span class="hljs-string">"得到锁2");
            }
        }
    }<span class="hljs-keyword">else{
        <span class="hljs-comment">//第二个线程会拿到o2的锁
        <span class="hljs-keyword">synchronized (o2){
            System.out.println(Thread.currentThread().getName()+<span class="hljs-string">"得到锁2");
            <span class="hljs-comment">//当想去拿o1的锁时,拿不到,因为已经被第一个线程占用
            <span class="hljs-keyword">synchronized (o1){
                System.out.println(Thread.currentThread().getName()+<span class="hljs-string">"得到锁1");
            }
        }
    }
}

}

java基础——线程笔记

执行上述代码,程序卡住不动,也没有结束进程。形成死锁

线程生命周期

  • NEW -> 创建
  • Runnable -> 可运行
    • Ready -> 就绪
    • Running -> 运行
  • TimedWaiting -> 及时等待
  • Waiting -> 等待
  • Blocked -> 阻塞
  • Terminated -> 已退出

 

java基础——线程笔记

线程生命周期图


END

posted @ 2021-09-19 15:56  你们都不上班吗  阅读(28)  评论(0)    收藏  举报