Java基础知识回顾——多线程

    科技2022-07-13  137

    多线程相关概念

    进程与线程概念很多地方都有,不打字复制了。补充点,

    1. 进程是操作系统进行资源分配的最小单位,每个进程都有独立的代码和数据空间,称为进程的上下文

    2. 线程是CPU调度的最小单位,是进程的一部分,只能由进程创建。一个进程有1~N个线程,这些线程共享进程的资源和程序代码。也就是说,一个Java进程(JVM进程)至少偶一个线程(主线程),对应Java中的main方法所在的线程。通过主线程可以创建更多的线程。

    3. 线程分为用户线程和守护线程。区别:守护线程会随着用户线程(主线程)的结束而结束,当所有的用户线程结束,程序就会终止,所有的守护线程也就终止。

    4. 系统可以给分配每个进程一段有限的CPU使用的时间(也可以称为CPU时间片)

    并发与并行

    经典举例 你吃饭吃到一半,电话来了,你一直到吃完了以后才去接,这就说明你不支持并发也不支持并行。 你吃饭吃到一半,电话来了,你停了下来接了电话,接完后继续吃饭,这说明你支持并发。 你吃饭吃到一半,电话来了,你一边打电话一边吃饭,这说明你支持并行。 并发的关键是你有处理多个任务的能力,不一定要同时。 并行的关键是你有同时处理多个任务的能力。 所以我认为它们最关键的点就是:是否是『同时』。

    作者:「已注销」 链接:https://www.zhihu.com/question/33515481/answer/58849148. 来源:知乎 著作权归作者所有。商业转载请联系作者获得授权,非商业转载请注明出处。

    线程状态

    线程和进程一样拥有7种状态:新建(NEW)、就绪(READY、RUNNABLE)、运行(RUNNING)、阻塞(BLOCKED)、等待(WAITING)、计时等待(TIME_WAITING)、终止(TERMINATED、DEAD)。

    run方法和start方法

    run方法是Runnable接口规定的一个线程类(Thread)必实现的方法

    我们可以看到,线程类是继承了Runnable接口的

    run方法中放的是实现功能的代码。

    线程实例、启动、这一过程我不太明白。

    忽略这一段文字,错误的地方我后面会修改。实例化线程对象后(这里我不明白,他到底是start启动线程后对象才实例出来,还是说在调用某一线程的start方法之前就已经实例了,和代码给我的感觉相冲突的,继续查资料),启动线程(start方法),某一线程对象的才会开始执行run方法

    package com.threadtest.test; import java.awt.BorderLayout; import javax.swing.JFrame; import javax.swing.JProgressBar; public class threadTest extends JFrame { /** serialVersionUID说明 * Java自带的序列化程序在序列化对象时,会将对象的类的信息联通对象本身实例信息(成员变量值) * 一起序列化到字节流中。 * 反序列化时,会根据这些类信息来还原(创建)出新对象。反序列化程序会根据serialVersionUID这 * 个常量值来判断反序列得到的类信息是否与原来的一致。如果我们不指定serialVersionUID的值,序 * 列化程序将把当前类的hashCode值赋给他 */ private static final long serialVersionUID = 1L; private Thread thA; private Thread thB; final JProgressBar progA = new JProgressBar(); final JProgressBar progB = new JProgressBar(); int count = 0; /* synchronized void doit() { }*/ /** * 两个进度条线程测试 * @param args */ public static void main(String[] args) { init(new threadTest(), 100, 100); } public threadTest() { super(); getContentPane().add(progA, BorderLayout.NORTH); getContentPane().add(progB, BorderLayout.SOUTH); progA.setStringPainted(true); progB.setStringPainted(true); //进度条显式数字字符 //A线程run方法覆写 //匿名内部类形式进行初始化 thA = new Thread(new Runnable() { int count = 0; @Override public void run() { //覆写run方法 while(true) { progA.setValue(++count); try { Thread.sleep(100); //休眠(阻塞)0.1s System.out.println("A、"); /** * join方法:当某个线程使用join方法加入到另一个线程时 * 另一个线程会等待该线程执行完毕后再继续执行上一个线程 */ thB.join(); //B线程开始执行 } catch (Exception e) { // TODO: handle exception } } } }); thA.start(); System.out.println("A线程启动"); //B线程run方法覆写 thB = new Thread(new Runnable() { int count = 0; public void run() { while(true) { progB.setValue(++count); try { Thread.sleep(100); //停留 System.out.println("B、"); } catch (Exception e) { // TODO: handle exception } if(count == 100) break; } } }); thB.start(); System.out.println("B线程启动"); } //初始化界面相关 public static void init(JFrame frame, int width, int height) { frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); frame.setSize(width, height); frame.setVisible(true); } } 当注释join方法时,两进程几乎是同时进行的 不注释掉join方法,则先按照上面描述一样进行

    线程池

    线程的创建和销毁会消耗资源。在大量并发的情况下,频繁的创建和销毁线程会严重降低系统的性能。因此,通常需要预先创建多个线程,并集中管理起来,形成一个线程池。在需要用到线程时,从池中拿出一个直接使用,执行完毕再放回池中。后续将会补充这一板块。emm…知识欠缺,继续充电

    线程安全与效率

    多线程的主要目的时提升程序的效率。但是保证线程安全是首要的前提。

    线程安全:指共享资源在多线程环境下时安全的,不会因为被多个线程并发的修改而出现数据破坏、丢失更新、死锁等问题。其中需要考虑到很多方面,例如:被多线程访问的全局变量、静态变量、文件、设备、Socket等等都属于共享资源。

    线程安全即多个线程之间并不共享资源(如此一来就没那么多的线程安全问题),或者说共享资源时,优化线程之间的公平、饥饿等方面的问题。

    Processed: 0.009, SQL: 8