Java高并发-多线程基础

Posted okokabcd

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Java高并发-多线程基础相关的知识,希望对你有一定的参考价值。

一、什么是线程

线程是进程内的执行单元。

二、线程的基本操作

2.1 状态与操作

技术分享图片

2.2 新建线程

Thread t1 = new Thread(new CreateThread());
t1.start();

# 直接覆盖run方法
# 传target实例,即Runnable接口实例

技术分享图片

2.3 终止线程

技术分享图片

2.4 中断线程

public void Thread.interrupt(); // 中断线程
public boolean Thread.isInterrupted(); // 判断是否被中断
public static boolean Thread.interrupted(); // 判断是否被中断,并清除当前中断状态

public static native void sleep(long millis) throws InterruptedException

代码

// 线程t1
public void run() {
    while(true) {
        Thread.yield();
    }
}
// 对线程t1进行中断操作,线程t1并不会做出响应
t1.interrupt();

// 执行下面这段代码的线程,会对中断做出响应
public void run() {
    while(true) {
        if (Thread.currentThread().isInterrupted()) {
            System.out.println("Interrupted!");
            break;
        }
        Thread.yield();
    }
}

sleep代码

// 在等待的过程中,也对中断操作做出响应
public void run() {
    while(true) {
        if (Thread.currentThread().isInterrupted()) {
            System.out.println('Interrupted!');
            break;
        }
        try {
            Thread.sleep(2000);
        } catch (InterruptedException e) {
            System.out.println("Interrupted When Sleep");
            // 设置中断状态,抛出异常后会清除中断标记位
            Thread.currentThread().interrupt();
        }
        Thread.yield();
    }
}

2.5 挂起和继续执行线程

suspend()不会释放锁

如果加锁发生在resume()之前,则发生死锁

这两个就法不推荐使用

技术分享图片

模拟死锁:

public class BadSuspend {
    public static Object u = 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(u) {
                System.out.println("in " + getName());
                Thread.currentThread().suspend();
            }
        }
    }
    public static void main(String[] args) throws InterruptedException {
        t1.start();
        Thread.sleep(100);
        t2.start();
        t1.resume();
        t2.resume();
        t1.join();
        t2.join();
    }
}

分析:

t1线程正常结束,t2线程死锁

技术分享图片

技术分享图片

2.6 等待线程结束和谦让

join,yeild

// 把自己占用的CPU机会释放掉,再和别人一起竞争CPU
public static native void yield();

// 当前线程未做完,主线程等待当前线程做完后再往下走
public final void join() throws InterruptedException
public final synchronized void join(long millis) throws InterruptedException

技术分享图片

技术分享图片

三、守护线程

在后台默默地完成一些系统性的服务,比如垃圾回收线程、JIT线程就可以理解为守护线程

当一个Java应用内,只有守护线程时,Java虚拟机就会自然退出

技术分享图片

四、线程优先级

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

t1.setPriority(Thread.MAX_PRIORITY);

五、基本的线程同步操作

5.1 synchronized

指定加锁对象:对给定对象加锁,进入同步代码前要获得给定对象的锁。

直接作用于实例方法:相当于对当前实例加锁,进入同步代码前要获得当前实例的锁。

直接作用于静态方法:相当于对当前类加锁,进入同步代码前要获得当前类的锁。

指定加锁对象

public class AccountingSync implements Runnable {
    static AccountingSync instance = new AccountingSync();
    static int i = 0;
    @Override
    public void run() {
        for (int j=0;j<100000;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<100000;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);
    }
}

技术分享图片

作用于静态方法:注意区别 作用于实例方法

技术分享图片

5.2 wait()/notify()

notify()之后,允许线程往下走,但是如果没有获得锁的话,也还是执行不了,t2.notifyAll()之后t1就可以往下执行了,但是此时t1还未获得object锁,必须等t2睡2秒后,获得object锁后执行。

技术分享图片

技术分享图片

以上是关于Java高并发-多线程基础的主要内容,如果未能解决你的问题,请参考以下文章

高并发编程必备基础 -- 转载自 并发编程网

高并发多线程基础之ThreadPoolExecutor源代码分析

高并发多线程基础之线程间通信与数据共享及其应用

多线程高并发,mysql中文文档

高并发多线程之线程基础中生命周期线程封闭cpu缓存

多线程高并发,mysql中文文档