前往小程序,Get更优阅读体验!
立即前往
首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >JUC学习之基础

JUC学习之基础

作者头像
Java那些事儿
发布2020-07-21 15:24:35
4600
发布2020-07-21 15:24:35
举报
文章被收录于专栏:Java那些事儿Java那些事儿

JUCjava.util.concurrent) 在 Java 5.0 提供了 JUC 包,在此包中增加了在并发编程中很常用的工具类,用于定义类似于线程的自定义子系统,包括线程池,异步 IO 和轻量级任务框架;还提供了设计用于多线程上下文中的 Collection 实现等

一、什么是JUC?

学习juc,主要就是这三个包的知识点。

二、多线程回顾

Thread、Runnable没有返回值,效率没有Callable高,可以抛异常。

线程的基本方法

  • getName(): 获取当前线程的名字
  • join(): 其他线程阻塞直至该线程执行完毕
  • sleep(int): 使该线程睡眠毫秒数
  • yeild(): 让出cpu,让cpu重新调度
  • getPriority(): 返回该线程的优先级
  • getState(): 返回该线程的状态
  • stop(): 线程停止--已废弃

1、之前见过的JUC包中的东西

Lock:

2、进程和线程

![image-20200711002948272](/Users/liuwenxu/Library/Application Support/typora-user-images/image-20200711002948272.png)

进程:一个程序就是一个进程,比如:QQ.exe。一个进程包含多个线程,但至少有一个线程

java中默认有几个线程? 2个,main和GC

线程:进程中的一个执行任务(控制单元),负责当前进程中程序的执行。比如,打开idea进程,敲代码是一个线程、自动保存又是一个线程。

Java中开启线程的方式:Thread、Runnable、Callable、线程池

线程的几种状态:

代码语言:javascript
复制
public enum State {
    // 新生状态
    NEW,
    // 运行状态
    RUNNABLE,
    // 被阻塞等待监视器锁定的线程处于此状态
    BLOCKED,
    // 正在等待另一个线程执行特定动作的线程处于此状态
    WAITING,
    // 正在等待另一个线程执行动作达到指定等待时间的线程处于此状态
    TIMED_WAITING,
    // 已退出的线程处于此状态
    TERMINATED;
}

Java能开启线程吗? 不能

代码语言:javascript
复制
    public synchronized void start() {
        if (threadStatus != 0)
            throw new IllegalThreadStateException();

        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);

        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }

    // 本地方法,Java无法直接操作硬件,底层是C++
    private native void start0();

重点是这句:private native void start0();,这是个本地方法,底层是c++。

注:更详细的两者对比可点击查看

3、并发和并行

通俗解释:

你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。 你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。 你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行

并发的关键是你有处理多个任务的能力,不一定要同时。 并行的关键是你有同时处理多个任务的能力。

所以它们最关键的点就是:是否是『同时』。

并发:多线程同时操作同一个资源,并发的本质就是充分利用CPU。

并行:多个程序同时运行

代码语言:javascript
复制
// 获取cpu的核数
Runtime.getRuntime().availableProcessors();

三、Lock锁

synchronized比较:

  • 所属包

Synchronized 是内置的java关键字;

Lock 是一个java类。

  • 使用方法

synchronized会自动释放锁;

lock需要手动释放锁,需要 lock() 和 unlock() 方法配合 try / finally 语句块来完成。

  • 等待是否可中断

synchronized 不可中断,除非抛出异常或者正常运行完成;

ReentrantLock 可中断,设置超时方法 tryLock(long timeout, TimeUnit unit)lockInterruptibly() 放代码块这,调用 interrupt() 方法可中断

  • 加锁是否公平

synchronized 非公平锁;

ReentrantLock 两者都可以,默认非公平锁,构造方法可以传入 boolean 值,true 为公平锁,false 为非公平锁

  • 锁绑定多个条件 Condition

Lock可以精确唤醒,而不是像 synchronized 要么随机唤醒一个线程要么唤醒全部线程。

synchronized

代码语言:javascript
复制
/**
 * Copyright (C), 2015-2020, https://www.liuwenxu.com/
 * FileName: SynchronizedTest
 * Author: liuwenxu
 * Date: 2020/7/10 5:42 下午
 * Description: 多线程synchronized   买票案例
 */
public class SynchronizedTest {
    public static void main(String[] args) {
        Tickets tickets = new Tickets();

        new Thread(() -> {for (int i = 0; i < 40; i++) tickets.sell();}, "A").start();
        new Thread(() -> {for (int i = 0; i < 40; i++) tickets.sell();}, "B").start();
        new Thread(() -> { for (int i = 0; i < 40; i++) tickets.sell();}, "C").start();
    }
}

class Tickets {
    private Integer num = 30;

    // 队列
    public synchronized void sell() {
        if (num > 0) {
            System.out.println("窗口" + Thread.currentThread().getName()
                    + "卖出第" + (num--) + "张票,还剩:" + num + "张");
        }
    }
}

Lock

代码语言:javascript
复制
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/**
 * Copyright (C), 2015-2020, https://www.liuwenxu.com/
 * FileName: LockTest
 * Author: liuwenxu
 * Date: 2020/7/10 5:42 下午
 * Description: 多线程lock   卖票案例
 */
public class LockTest {
    public static void main(String[] args) {
        Tickets2 tickets = new Tickets2();

        new Thread(()->{ for (int i = 0; i < 40; i++) tickets.sell(); },"A").start();
        new Thread(()->{ for (int i = 0; i < 40; i++) tickets.sell(); },"B").start();
        new Thread(()->{ for (int i = 0; i < 40; i++) tickets.sell(); },"C").start();
    }
}

class Tickets2 {
    private Integer num = 30;
    // lock三部曲
    // Lock l = ...; l.lock(); try { // access the resource protected by this lock } finally { l.unlock(); }
    Lock l = new ReentrantLock();

    public void sell() {
        l.lock();
        try {
            if (num > 0) {
                System.out.println("窗口" + Thread.currentThread().getName() + "卖出第" + (31-(num--)) + "张票,还剩:" + num + "张");
            }
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            l.unlock();
        }
    }
}

Q.E.D.

本文参与 腾讯云自媒体分享计划,分享自作者个人站点/博客。
原始发表:2020-07-11,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 作者个人站点/博客 前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 一、什么是JUC?
  • 二、多线程回顾
    • 1、之前见过的JUC包中的东西
      • 2、进程和线程
        • 3、并发和并行
        • 三、Lock锁
          • 和synchronized比较:
            • synchronized
              • Lock
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档