多线程TOP50

什么是线程?

线程是CPU的最小执行单元,当依附在进程之下的。程序就是一个进程,比如windows的.exe程序,或者android系统的一个app就是一个独立的进程,一个进程可以创建多个线程。

特点

  • 线程拥有自己的计数器、堆栈、局部变量等属性
  • 提高执行效率和用户体验,执行一些耗时的异步任务。

什么是线程安全和线程不安全?

  • 线程安全
    线程安全就是在多线程下,对数据或者代码进行加锁保护。只有获得锁的线程才能执行代码,没有获得锁的线程会处于堵塞状态,等待释放锁后才能执行。这样做保证了数据在多线程执行下的安全性

  • 线程不安全
    多线程的代码或者数据如果没有使用同步机制,可能会出现数据不能达到预期的结果,出现很多脏数据。

什么是自旋锁?
什么是Java内存模型?
什么是CAS?
什么是乐观锁和悲观锁?
什么是AQS?
什么是原子操作?在Java Concurrency API中有哪些原子类(atomic classes)?
什么是Executors框架?

什么是阻塞队列?如何使用阻塞队列来实现生产者-消费者模型?

阻塞队列就是在队列的基础上增加了二个操作

    1. 支持阻塞插入方法
      队列满时,插入元素的的线程会阻塞,直到队列不满。
    1. 支持阻塞移除方法
      队列为空时,获取元素的线程处于阻塞等待队列不为空

生产消费者模式
这个模式就是运用了以上增加的二个方法,一个线程创建创建队列元素,一个线程消费队列元素。

class Queque {


    @Test
    public fun test() {
        var queue = LinkedBlockingQueue<Any>(10)
        Thread(Producer(queue)).start()

        Thread(Consumer(queue)).start()


        Thread.sleep(1000)
//        System.exit(0)


    }


    //生产者
    class Producer(var queue: BlockingQueue<Any>) : Runnable {


        override fun run() {
            try {
                while (true) {
                    var any = getObject()
                    queue.put(any)
                    System.out.println("生产者资源队列大小 ${queue.size}")
                }
            } catch (ex: Exception) {
                System.out.println("******生产者中断******")
            }
        }

        fun getObject(): Any {
            try {
//                Thread.sleep(1000)
            } catch (ex: Exception) {
                System.out.println("******生产者创建中断******")
            }
            return Any()
        }
    }


    //消费者

    class Consumer(var queue: BlockingQueue<Any>) : Runnable {


        override fun run() {

            try {
                while (true) {
                    var any = queue.take()
                    System.out.println("消费者资源队列大小 ${queue.size}")
                    take(any)
                }
            } catch (e: Exception) {
                System.out.println("消费者中断")
            }

        }


        fun take(any: Any) {
            try {
                Thread.sleep(1000)
            } catch (e: Exception) {
                System.out.println("消费者使用中断")
            }
            System.out.println("消费对象 $any")
        }
    }
}

什么是Callable和Future?
什么是FutureTask?
什么是同步容器和并发容器的实现?

什么是多线程?优缺点?

  • 多线程
    线程是存在于进程之中的它相当于一个任务,当个线程就是单个任务,多个线程就是多个任务,多线程可以提高程序的执行效率一般用于去处理那些比较耗时的操作,比如IO、网络、文件读写的操作。

  • 优缺点

什么是多线程的上下文切换?

ThreadLocal的设计理念与作用?

  • 设计理念
  1. 每一个线程都会持有一个ThreadLocalmap(静态内部类)
  2. ThreadLocalmap里有一个Entry数组,它是弱引用级别的一个子类。
  3. Entry数组会以当前ThreadLocal作为Key
  4. 所以每个线程持有不同的Entry数组,只有获取值得时候必须是和set方法调用线程,处于同一个线程。
  • 作用
    ThreadLocal用于在线程中存储数据,不想被其他线程访问,只能被调用set数据的线程所访问。

ThreadPool(线程池)用法与优势?

用法

  1. 通过ThreadPoolExecutor类来创建一个线程池主要参数有,线程次大小、线程池最大大小、线程活动保持时间、任务队列等。

  2. 通过Executors类工厂来创建

  • Executors.newSingleThreadExecutor();//单个后台线程

  • Executors.newFixedThreadPool(10);//固定大小线程池

  • Executors.newCachedThreadPool();//无界线程池,可以进行自动线程回收

  • Executors.newScheduledThreadPool(10);//定时线程池

优势
1.节省系统资源,线程池可以提高线程的复用效率,节省内存开销。

  1. 方便管理,可以对线程归纳到一起实行统一管理

Concurrent包里的其他东西:ArrayBlockingQueue、CountDownLatch等等。

synchronized和ReentrantLock的区别?
Semaphore有什么作用?
Java Concurrency API中的Lock接口(Lock interface)是什么?对比同步它有什么优势?
Hashtable的size()方法中明明只有一条语句”return count”,为什么还要做同步?
ConcurrentHashMap的并发度是什么?
ReentrantReadWriteLock读写锁的使用?
CyclicBarrier和CountDownLatch的用法及区别?
LockSupport工具?
Condition接口及其实现原理?
Fork/Join框架的理解?

wait()和sleep()的区别?

  • wait
    wait是Object方法它会让一个线程进入等待状态,通过需要nofity来唤醒

  • sleep
    sleep是Thread的方法,调用它会让一个线程进入等待超时状态,根据传入的时间会自己唤醒。

线程的五个状态(五种状态,创建、就绪、运行、阻塞和死亡)?

java线程在执行过程中,可能会处于以下图中的六种状态,在给定的一个时刻线程只能处于其中的一个状态。

  • NEW&初始状态
    创建一个线程但是没有调用.start方法
new Thread();
  • RUNNABLE&运行状态
    调用start就会处于运行状态

  • BLOCKED&阻塞状态
    这个状态就是遇到了synchronized代码块或者方法,就会处于阻塞状态,如果获得了锁就会切换到运行状态

  • WAITING&等待状态
    表示线程进入等待状态,进入该状态需要其他线程做出一些特定的动作才能唤醒,wait()、join()、park()、方法都会导致线程进入等待状态,通过notify、notifyAll、unpark又会切回运行状态

  • TIME_WAITING&超时状态
    超时等待状态、不同于等待,这个状态如果没有被唤醒,达一定时间会自行返回。

  • TERMINATED*终止状态
    线程执行完毕的状态。

image

一张图看懂,每个状态进入的时间和切换的时机。


image

Thread源码中的State枚举类对状态的说明和定义

public enum State {
        /**
         * Thread state for a thread which has not yet started.
         */
        NEW,

        /**
         * Thread state for a runnable thread.  A thread in the runnable
         * state is executing in the Java virtual machine but it may
         * be waiting for other resources from the operating system
         * such as processor.
         */
        RUNNABLE,

        /**
         * Thread state for a thread blocked waiting for a monitor lock.
         * A thread in the blocked state is waiting for a monitor lock
         * to enter a synchronized block/method or
         * reenter a synchronized block/method after calling
         * {@link Object#wait() Object.wait}.
         */
        BLOCKED,

        /**
         * Thread state for a waiting thread.
         * A thread is in the waiting state due to calling one of the
         * following methods:
         * <ul>
         *   <li>{@link Object#wait() Object.wait} with no timeout</li>
         *   <li>{@link #join() Thread.join} with no timeout</li>
         *   <li>{@link LockSupport#park() LockSupport.park}</li>
         * </ul>
         *
         * <p>A thread in the waiting state is waiting for another thread to
         * perform a particular action.
         *
         * For example, a thread that has called <tt>Object.wait()</tt>
         * on an object is waiting for another thread to call
         * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
         * that object. A thread that has called <tt>Thread.join()</tt>
         * is waiting for a specified thread to terminate.
         */
        WAITING,

        /**
         * Thread state for a waiting thread with a specified waiting time.
         * A thread is in the timed waiting state due to calling one of
         * the following methods with a specified positive waiting time:
         * <ul>
         *   <li>{@link #sleep Thread.sleep}</li>
         *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
         *   <li>{@link #join(long) Thread.join} with timeout</li>
         *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
         *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
         * </ul>
         */
        TIMED_WAITING,

        /**
         * Thread state for a terminated thread.
         * The thread has completed execution.
         */
        TERMINATED;
    }

start()方法和run()方法的区别?

  • start
    start是Thrad的方法,它是用来真正的启动一个线程,调用完后线程状态就是新建的状态

  • run
    run是Runnable接口的方法,这个方法和普通方法没有区别,它一般作用于线程的执行体。

Runnable接口和Callable接口的区别?

volatile关键字的作用?

让子线程每次读取值得时候都强制从主内存中读取

在多线程情况下,每个线程都会有自己的一个本地变量栈。如果从主线程中读取一个变量,本地变量栈会从主内存中拷贝一个副本。以后每次子线程操作变量就是操作的副本,它的作用就是让线程每次都从主内存中读取。

Java中如何获取到线程dump文件?
线程和进程有什么区别?

线程实现的方式有几种(四种)?

  1. 继承Thread类调用.start方法,重写run方法,这种方式不需要传入Runable对象。
 static class ThreadA extends Thread {
        @Override
        public void run() {
            System.out.println(Thread.currentThread().getName());
        }
    }
  1. 通过创建一个Thread类执行一个线程,传入Runable接口调用Thread的.start方法来开启一个线程
  1. Thread接收一个FutureTask来启动一个线程
 @Test
    fun testThread() {
        System.out.println(Thread.currentThread().id)
        var callable = ThreadA<String>()
        var oneTask = FutureTask<String>(callable)
        var t = Thread(oneTask)
        t.start()
    }

    class ThreadA<T> : Callable<T> {
        override fun call(): T? {
            System.out.println(Thread.currentThread().id)
            return null;
        }

    }
  1. ExecutorService来创建一个线程池启动

高并发、任务执行时间短的业务怎样使用线程池?并发不高、任务执行时间长的业务怎样使用线程池?并发高、业务执行时间长的业务怎样使用线程池?
如果你提交任务时,线程池队列已满,这时会发生什么?
锁的等级:方法锁、对象锁、类锁?
如果同步块内的线程抛出异常会发生什么?
并发编程(concurrency)并行编程(parallellism)有什么区别?
如何保证多线程下 i++ 结果正确?
一个线程如果出现了运行时异常会怎么样?

如何在两个线程之间共享数据?

如果执行代码是一样的话可以创建二个Thread线程,使用一个Runble变量传入,这样操作的就是同一个对象的变量了实现了共享。

@Test
    fun testThread3() {
        var r = Runable1()
        var t1 = Thread(r)
        var t2 = Thread(r)
        t1.start()
        t2.start()
    }


    class Runable1 : Runnable {

        var count = 120
        override fun run() {
            synchronized(this) {
                while (count > 0) {
                    count--
                    System.out.println("剩余票数$count 执行线程="+Thread.currentThread().name)
                }
            }

        }

    }

还有一种是代码不一样的情况,这样可以创建多个Runable对象,把要操作的数据封装到对象中,传入runable对象,加入同步关键字,这样虽然是不同的任务线程但是他们操作的同一个对象,也可以把要操作的数据设置成全局类型的,多个线程可以直接操作同一个变量。

生产者消费者模型的作用是什么?

怎么唤醒一个阻塞的线程?

看什么情况下让线程进入了堵塞

  • Synchronize
    如果遇到同步关键字的话,未获取到锁会进入堵塞状态,等待获取锁后就会重新唤醒线程

  • notify notifyAll
    这种情况是通过对象的wait让线程进入了等待状态,通过这二个方法可以让等待的线程,重新唤醒进入运行状态。

线程的Join是什么?

join是Thread的一个方法,主要作用是在当前线程中调用另外一个线程的join方法,当前线程就会等待调用join方法的线程执行完毕后才继续往下执行。

t.join完后,main线程必须会等待t1线程完成之后才继续执行。如果不加join有可能会出现t2线程先执行。

 @Test
    fun test() {
        var t1 = Thread(Runnable {
            Thread.sleep(1000)
            System.out.println(Thread.currentThread().name)
        })

        var t2 = Thread(Runnable {
            System.out.println(Thread.currentThread().name)
        })

        t1.start()
        t1.join()
        t2.start()

        Thread.sleep(1000)

    }

Java中用到的线程调度算法是什么
单例模式的线程安全性?
线程类的构造方法、静态块是被哪个线程调用的?
同步方法和同步块,哪个是更好的选择?

如何检测死锁?怎么预防死锁?

  • 死锁代码
public static void main(String[] args) {


        Thread t1 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (A) {
                    try {
                        Thread.sleep(2000);
                        System.out.println("A");
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    synchronized (B) {
                        System.out.println("1");
                    }
                }
            }
        });

        Thread t2 = new Thread(new Runnable() {
            @Override
            public void run() {
                synchronized (B) {
                    System.out.println("B");
                    synchronized (A) {
                        System.out.println("2");
                    }
                }
            }
        });

        t1.start();
        t2.start();

    }
  • 检测死锁
    dump线程查看,死锁会导致系统永久无反应,业务逻辑是可以知道的。

  • 预防死锁

  1. 避免一个线程获取多个锁
  2. 一个线程不要过多占用资源
  3. 使用定时锁
  4. 对于数据库锁加锁解锁必须在一个数据库连接里,否则会出现解锁失败情况

掘金

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 214,444评论 6 496
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 91,421评论 3 389
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 160,036评论 0 349
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 57,363评论 1 288
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 66,460评论 6 386
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 50,502评论 1 292
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 39,511评论 3 412
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 38,280评论 0 270
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 44,736评论 1 307
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,014评论 2 328
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 39,190评论 1 342
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 34,848评论 5 338
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 40,531评论 3 322
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,159评论 0 21
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 32,411评论 1 268
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 47,067评论 2 365
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 44,078评论 2 352

推荐阅读更多精彩内容

  • 本文是我自己在秋招复习时的读书笔记,整理的知识点,也是为了防止忘记,尊重劳动成果,转载注明出处哦!如果你也喜欢,那...
    波波波先森阅读 11,248评论 4 56
  • 进程和线程 进程 所有运行中的任务通常对应一个进程,当一个程序进入内存运行时,即变成一个进程.进程是处于运行过程中...
    胜浩_ae28阅读 5,096评论 0 23
  • 为什么使用线程池 当我们在使用线程时,如果每次需要一个线程时都去创建一个线程,这样实现起来很简单,但是会有一个问题...
    闽越布衣阅读 4,284评论 10 45
  • 绵绵青翠竹巷深处,流月华空幻缥缈, 山外云中。 望穿重山经天未散,伴生好章岁凭年, 悠逢知己。 遥思沧海萍旅茫茫,...
    空明源阅读 245评论 0 0
  • IOT的核心: 连接稳定性和安全。连接稳定性包括大规模接入设备后,服务还能保持较低的响应和稳定。 这一点非常困难。...
    王阿宝阅读 2,146评论 0 0