侧边栏壁纸
博主头像
Sir丶雨轩博主等级

一个90的萌新码农,热爱编程热爱生活 编程交流群:875477818

  • 累计撰写 48 篇文章
  • 累计创建 81 个标签
  • 累计收到 0 条评论

目 录CONTENT

文章目录

Java多线程基础

Sir丶雨轩
2020-07-02 / 0 评论 / 1 点赞 / 93 阅读 / 5,407 字 / 正在检测是否收录...
温馨提示:
本文最后更新于 2021-12-23,若内容或图片失效,请留言反馈。部分素材来自网络,若不小心影响到您的利益,请联系我们删除。

什么是线程
线程是进程内的执行单元

线程的状态
NEW(初始状态)
RUNABLE(可运行状态)
BLOCKED(阻塞状态)
WAITNG(等待状态)
RUNNING(运行状态)
DEAD(死亡状态)
Untitled.png

创建一个线程
1.重写Thread的Run方法

new Thread(){
    @Override
    public void run() {
        System.out.println(1);
     }
}.start();

2.实现Runable接口

new Thread(new Runnable() {
    @Override
    public void run() {
        System.out.println(1);
    }
}).start();

终止线程
Thread.stop();不推荐使用,它会释放所有的monitor可以会导致多线程环境下数据不一致

使用中断

//当前线程没有收到中断信号时才工作

while(Thread.cuurentThread().isInterrupted()){
    // do soming
}

// 发送中断信号
t1.interrupt();
中断线程
public void Thread.interrupt();// 中断线程

public boolean Thread.isInterrupt();// 判断是否被中断

public static boolean Thread.interrupted() // 判断是否被中断,并清除当前中断状态

挂机(suspend)和继续执行(resume)
suspend() 不会释放锁
如果加锁发生在resume()之前,则死锁发生

        public static Object lock = new Object();
    static ChangeObjectThread t1 = new ChangeObjectThread("t1");
    static ChangeObjectThread t2 = new ChangeObjectThread("t2");
    public static class ChangeObjectThread extends Thread {
        public ChangeObjectThread(String name) {
            super.setName(name);
        }
        @Override
        public void run() {
            synchronized (lock) {
                System.out.println("in " + getName());
                Thread.currentThread().suspend();
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        t1.start();
        Thread.sleep(1000);
        t2.start();
        t1.resume();
        t2.resume();
        t1.join();
        t2.join();
    }

理论来说,线程t1,t2启动,挂起,然后继续执行,主函数应该会很快结束,但实际情况是 t1线程没问题正常结束,t2线程 由于通知继续执行的时候 还没有走到挂起代码,所以t2线程会一直处于挂起状态

等待线程结束(join)和谦让(yeild)
public final void join() throws InterrptedException 等待线程执行完毕
public final synchronized void join(long millis) throws InterrptedException
public static void yeild() 暂时释放自己的执行权
守护线程
在后台默默地完成一些系统性的服务,比如垃圾回收线程,JIT线程就可以理解为守护线程
当一个Java应用内,只有守护线程时,Java虚拟机就会自然退出
需要在线程启动之前进行设置

public static void main(String[] args) throws InterruptedException {
        Thread thread = new Thread() {
            @Override
            public void run() {
                while(true){
                    System.out.println("I am daemon Thread");
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };
        thread.setDaemon(true);
        thread.start();
        Thread.sleep(1000);
        System.out.println("main thread end");
    }

线程优先级
高优先级的线程更容易再竞争中获胜

public final static int MIN_PRIORITY = 1;
public final static int NORM_PRIORITY = 5;
public final static int MAX_PRIORITY = 10;
public static class HighPriority extends Thread {
        static int count = 0;
        @Override
        public void run() {
            while (true) {
                synchronized (PriorityDemo.class) {
                    count++;
                    if (count > 100000000) {
                        System.out.println("HighPriority is complete");
                        break;
                    }
                }
            }
        }
    }
    public static class LowPriority extends Thread {
        static int count = 0;
        @Override
        public void run() {
            while (true) {
                synchronized (PriorityDemo.class) {
                    count++;
                    if (count > 100000000) {
                        System.out.println("LowPriority is complete");
                        break;
                    }
                }
            }
        }
    }
    /**
     * 高优先级先完成的次数多,但是不保证
     * @param args
     */
    public static void main(String[] args) {
        Thread high = new HighPriority();
        Thread low = new LowPriority();
        high.setPriority(Thread.MAX_PRIORITY);
        low.setPriority(Thread.MIN_PRIORITY);
        low.start();
        high.start();
    }

基本的线程同步操作
synchronized
指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。
直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。
直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁
加锁对象

public class AccountingSync implements Runnable{
    static final AccountingSync instance = new AccountingSync();
    static int i = 0;
    @Override
    public void run() {
        for (int j = 0; j < 100000000; j++) {
            synchronized (instance){
                i++;
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

加锁实例方法

public class AccountingSync2 implements Runnable {
    static AccountingSync2 instance = new AccountingSync2();
    static int i = 0;
    public synchronized void increase() {
        i++;
    }
    @Override
    public void run() {
        for (int j = 0; j < 10000000; j++) {
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(instance);
        Thread t2 = new Thread(instance);
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

加锁实例方法,由于这个实例是new的两个实例导致获取的不是同一把锁

public class AccountingSyncBad implements Runnable {
    static int i = 0;
    public synchronized void increase() {
        i++;
    }
    @Override
    public void run() {
        for (int j = 0; j < 10000000; j++) {
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new AccountingSyncBad());
        Thread t2 = new Thread(new AccountingSyncBad());
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

加锁静态方法,类锁 会对AccountingSyncClass.class 进行加锁由于是同一把锁所以数据没问题

public class AccountingSyncClass implements Runnable {
    static int i = 0;
    public  static synchronized void increase() {
        i++;
    }
    @Override
    public void run() {
        for (int j = 0; j < 10000000; j++) {
            increase();
        }
    }
    public static void main(String[] args) throws InterruptedException {
        Thread t1 = new Thread(new AccountingSyncClass());
        Thread t2 = new Thread(new AccountingSyncClass());
        t1.start();
        t2.start();
        t1.join();
        t2.join();
        System.out.println(i);
    }
}

Object.wait()
会使当前线程等待,必须拥有当前对象的锁,并且会释放当前对象的所有权,并等待其他线程通知当前线程继续执行

Object object = new Object();
    synchronized (object){
        object.wait();
}

Object.notify()
唤醒一个等待在当前对象的线程锁,必须拥有当前对象的锁,wait的线程必须等待此同步块的代码完成后,在去竞争锁

如果有多个线程的话 随机唤醒一个,notifyAll() 唤醒所有

Object object = new Object();
    synchronized (object){
        object.notify();
}

wait notify

public static void main(String[] args) {
        final Object object = new Object();
        new Thread() {
            @Override
            public void run() {
                synchronized (object) {
                    System.out.println(System.currentTimeMillis() + ":T1 start");
                    try {
                        object.wait();
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(System.currentTimeMillis() + ":T1 end");
                }
            }
        }.start();
        new Thread() {
            @Override
            public void run() {
                synchronized (object) {
                    System.out.println(System.currentTimeMillis() + ":T2 start");
                    object.notify();
                    try {
                        Thread.sleep(2000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(System.currentTimeMillis() + ":T2 end");
                }
            }
        }.start();
    }
1

评论区