目录
一 概述
1.什么是进程?" > 1.什么是进程?
2.什么是线程?" > 2.什么是线程?
3.线程与进程的区别?" > 3.线程与进程的区别?
4.多线程的设计目的、用途、意义" > 4.多线程的设计目的、用途、意义
5.CPU调度模式" > 5.CPU调度模式
二 线程创建" >二 线程创建
1.Java SE API 提供了两种创建线程的方式:" > 1.Java SE API 提供了两种创建线程的方式:
2.无论采用哪种方式,需要执行的任务都必须放在run方法中。" > 2.无论采用哪种方式,需要执行的任务都必须放在run方法中。
3.两种创建方式的区别:" > 3.两种创建方式的区别:
⑵实现资源共享的方式不同" >⑵实现资源共享的方式不同
5.通过继承Thread的方式实现资源共享:" >5.通过继承Thread的方式实现资源共享:
三 线程生命周期" >三 线程生命周期
1.什么是线程的生命周期?" > 1.什么是线程的生命周期?
2.线程生命周期的意义" > 2.线程生命周期的意义
3.生命周期的几个阶段:" > 3.生命周期的几个阶段:
四 线程的加入" >四 线程的加入
五 线程优先级" >五 线程优先级
六 线程礼让" >六 线程礼让
七 同步机制" >七 同步机制
1.什么是线程同步机制?" > 1.什么是线程同步机制?
2.同步机制的目的" > 2.同步机制的目的
3.什么是线程安全问题?" > 3.什么是线程安全问题?
⑴线程安全问题产生条件" >⑴线程安全问题产生条件
⑵第一个线程获取了共享数据,操作结束前,第二个线程修改了该数据,导致第一个线程运算时采用的不是获取时的数据。" >⑵第一个线程获取了共享数据,操作结束前,第二个线程修改了该数据,导致第一个线程运算时采用的不是获取时的数据。
4.同步机制解决线程安全问题的原理" > 4.同步机制解决线程安全问题的原理
5.类锁" > 5.类锁
6.synchronized关键字" > 6.synchronized关键字
7.判断条件的设置" > 7.判断条件的设置
不存在线程安全问题的做法:" >不存在线程安全问题的做法:
八 死锁" >八 死锁
1.什么是死锁?" > 1.什么是死锁?
2.怎么避免死锁?" > 2.怎么避免死锁?
九 守护线程" >九 守护线程
1.用户线程?" > 1.用户线程?
2.主线程属于用户线程。" > 2.主线程属于用户线程。
3.什么是守护线程?" > 3.什么是守护线程?
4.守护线程创建" > 4.守护线程创建
5.守护线程的作用" > 5.守护线程的作用
6.JVM在所有的用户线程执行完毕后终止,无论此时守护线程是否执行完毕。" >6.JVM在所有的用户线程执行完毕后终止,无论此时守护线程是否执行完毕。
7.守护线程运行在后台,所有用户线程结束后,自动结束。" > 7.守护线程运行在后台,所有用户线程结束后,自动结束。
十 wait与sleep方法对比" >十 wait与sleep方法对比
1.存在范围" > 1.存在范围
2.作用" > 2.作用
3.使用方法" > 3.使用方法
4.相关方法" > 4.相关方法
十一 ThreadLocal" >十一 ThreadLocal
十二 GroboUtils多线程测试" >十二 GroboUtils多线程测试
   1.JUnit测试不支持多线程,GroboUtils提供了对多线程测试的支持,使用时需要导入架包。" >    1.JUnit测试不支持多线程,GroboUtils提供了对多线程测试的支持,使用时需要导入架包。
    2.几个比较重要的类:" >     2.几个比较重要的类:
    3.测试步骤" >     3.测试步骤
⑵创建测试线程数组,将需要测试的TestRunnable实现类传入其中:" >⑵创建测试线程数组,将需要测试的TestRunnable实现类传入其中:
⑶根据测试线程数组创建线程管理与运行对象并开启多线程:" >⑶根据测试线程数组创建线程管理与运行对象并开启多线程:
首页 Java java教程 什么是进程与线程?

什么是进程与线程?

Jun 25, 2017 am 10:18 AM
线程

一 概述

1.什么是进程?

进程是一个相对独立的执行单位。

2.什么是线程?

进程的一部分,进程中实际的任务执行者,必须依附于进程。线程对进程的依赖主要体现在:

  • 线程不能脱离进程开启,必须在进程开启的前提下开启。

  • 线程有时必须从进程中获取数据。

3.线程与进程的区别?

线程与进程是两个相对的概念,一个对象相对于它拥有的执行单位被称为进程,从自身所属的上级执行者来看,又被称作线程。

4.多线程的设计目的、用途、意义

CUP在任何一个时间点都只能执行一个线程,多线程的本质是多个任务高速交替执行。如果多个线程间不存在数据交换,可以单独执行,采用多线程并不能减少总的执行时间。

多线程设计的主要目的不是为了提高执行速度,而是相对平均地执行每一个线程,不致使某一个线程长时间持有CPU时间片,其他线程长时间处于等待状态。由于CPU时间片在多个线程间切换迅速,超出了人类感官所能察觉的范围,所以感觉多个任务都是执行。

例如,当多个人访问同一个网站,每一个人都需要5分钟,如果不采用多线程,同时只允许一个人进入网站,其他多数人都要等待5分钟,用户体验很差。这是采用多线程,一个人进入以后,CPU转向其他用户,让其他用户陆续进入,用户体验就提高了,尽管总的执行时间并没有减少。

5.CPU调度模式

  • 分时调度模式:系统平均地为各个线程分配CPU时间片。

  • 抢占式调度模式:各个线程抢夺CPU时间片,CPU时间片在线程间不均匀分配。

二 线程创建

1.Java SE API 提供了两种创建线程的方式:

  • 实现Runnable接口,将实现类的对象作为参数传入Thread的构造器中。

  • 直接继承Thread类。

2.无论采用哪种方式,需要执行的任务都必须放在run方法中。

3.两种创建方式的区别:

⑴Java采用单继承,即一个类只能继承一个父类,而允许一个类实现多个接口,采用继承Thread的方式创建线程,就使本类失去了唯一的一次继承机会。

⑵实现资源共享的方式不同

  • 首先需要明确的一点,通过继承Thread创建线程的方式也可以实现资源共享,只是由于通过new关键字创建的多个线程是不同的对象,那么共享资源只能来自于外部,通常通过构造器注入。

  • 而通过实现Runnable接口的方式创建线程,可以利用同一个实现类对象创建多个线程,实现了资源共享,共享资源来自线程内部。

4.采用实现Runnable接口的方式创建线程,不仅保留了唯一的继承机会,而且在实现资源共享的操作相对简单,所以一般采用该方式创建线程。

5.通过继承Thread的方式实现资源共享:

提供共享资源的外部类

package com.test.thread.extendsThread;public class MyClass {public int count;

}
登录后复制

Thread线程子类

package com.test.thread.extendsThread;public class MyThread extends Thread {private MyClass obj;public MyThread() {super();
    }public MyThread(MyClass obj) {super();this.obj = obj;
    }

    @Overridepublic void run() {
        System.out.println("obj=" + obj);while (true) {synchronized (obj) {if (obj.count > 0) {try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "----当前数量=" + obj.count--);
                } elsereturn;
            }
        }

    }

}
登录后复制

测试类

package com.test.thread.extendsThread;import org.junit.Test;import com.test.thread.synchronizedTest.demo02.MyTestRunnable;import net.sourceforge.groboutils.junit.v1.MultiThreadedTestRunner;import net.sourceforge.groboutils.junit.v1.TestRunnable;public class ThreadExtendsTest {/** * JUnit单元测试不支持多线程测试,使用GroboUtils进行多线程测试(导入架包)
     * 
     * @throws Throwable     */@Testpublic void test01() throws Throwable {
        MyClass obj = new MyClass();
        obj.count = 10;
        MyThread myth01 = new MyThread(obj);
        MyThread myth02 = new MyThread(obj);
        MyThread myth03 = new MyThread(obj);
        MyTestRunnable t01 = new MyTestRunnable(myth01);
        MyTestRunnable t02 = new MyTestRunnable(myth02);
        MyTestRunnable t03 = new MyTestRunnable(myth03);
        TestRunnable[] tr = new TestRunnable[3];
        tr[0] = t01;
        tr[1] = t02;
        tr[2] = t03;
        MultiThreadedTestRunner mttr = new MultiThreadedTestRunner(tr);
        mttr.runTestRunnables();
    }// 放在主线程中测试public static void main(String[] args) {
        MyClass obj = new MyClass();
        obj.count = 10;
        MyThread t01 = new MyThread(obj);
        MyThread t02 = new MyThread(obj);
        MyThread t03 = new MyThread(obj);
        t01.setName("t01");
        t02.setName("t02");
        t03.setName("t03");
        t01.start();
        t02.start();
        t03.start();
    }
}
登录后复制

 

三 线程生命周期

1.什么是线程的生命周期?

由不同阶段构成的线程从出生到死亡的整个过程,叫做线程的生命周期。

2.线程生命周期的意义

了解线程的生命周期能够更好地掌握线程的运行情况,比如线程的就绪状态,意味着不是调用start方法之后,线程立即执行。

3.生命周期的几个阶段:

  • 出生状态:线程创建完成,尚未开启前的状态。

  • 就绪状态:调用start方法开启线程,线程尚未运行的状态。

  • 运行状态:线程获取CPU时间片执行时的状态。

  • 休眠状态:线程调用sleep方法后进入指定时长的休眠状态,时间结束进入就绪状态。

  • 等待状态:监听对象在线程内部调用wait方法后,线程失去对象锁,进入等待状态。

  • 阻塞状态:线程发出输入或者输出请求后进入阻塞状态。

  • 死亡状态:run方法执行完毕,线程死亡。

四 线程的加入

一个线程A在另一个线程B内部调用join方法,B线程中止,A线程开始执行,A线程执行完毕,B线程才开始执行。

五 线程优先级

线程优先级设定了线程获取CPU时间片的概率,仅仅是一种概率,不能保证优先级高的线程一定优先获得CPU时间片。

线程优先级分为10个等级,从1-10,数值越大,优先级越高,通过setProprity(int)方法设置。

六 线程礼让

Thread.yield,线程礼让只是通知当前线程可以将资源礼让给其他线程,并不能保证当前线程一定让出资源。

七 同步机制

1.什么是线程同步机制?

使得同一资源同一时刻只能有一个线程访问的安全机制,即一个线程访问完毕,其他线程才能访问。

2.同步机制的目的

由于目标资源同一时刻只有一个线程访问,解决了线程安全问题。

3.什么是线程安全问题?

⑴线程安全问题产生条件

  • 多线程并发访问。

  • 存在可修改的共享数据。

⑵第一个线程获取了共享数据,操作结束前,第二个线程修改了该数据,导致第一个线程运算时采用的不是获取时的数据。

4.同步机制解决线程安全问题的原理

synchronized(共享对象){ 修改共享数据的代码 }
登录后复制

上述操作给修改共享数据的代码加了一把对象锁。任何一个对象只有一把对象锁,线程只有获得了对象锁才能访问加锁的资源。一个线程获取了对象锁,执行加锁的代码,执行完毕,归还对象锁,其他线程开始争夺对象锁,访问资源。

5.类锁

synchronized关键字加到静态方法上时,形成类锁,执行该方法上必须获取类锁。

类锁与对象锁是两种不同的锁,允许一个线程持有类锁,另一个线程持有对象锁。

6.synchronized关键字

synchronized关键字加在成员方法,该方法成为同步成员方法,由于一个对象只有一把对象锁,一个线程访问了一个同步成员方法,其他线程不能访问其他同步成员方法。

同步方法不可以被继承,同步方法在子类中失去同步机制。

7.判断条件的设置

在同步机制中,如果同步代码的执行需要满足一定条件,那么将判断条件放在锁内,保证当前获取了锁的线程在执行同步代码时满足执行条件。如果放在锁外,有可能出现当前线程获取了锁以后不满足执行条件的情况。

不存在线程安全问题的做法:

public void run() {
        System.out.println("obj=" + obj);while (true) {synchronized (obj) {if (obj.count > 0) {try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                    System.out.println(Thread.currentThread().getName() + "----当前数量=" + obj.count--);
                } elsereturn;
            }
        }

    }
登录后复制

如果将判断条件obj.count>0放在while语句中,可能出现某个线程进入while语句时count为1,满足条件,进入,等待获取对象锁。当前持有对象锁的线程执行完毕,count变为0,等待线程获取对象锁,在count=0的情况下执行同步块,判断条件失效。

 

八 死锁

1.什么是死锁?

线程A需要多把锁,线程B持有A缺少的锁,缺少A持有的锁,由于线程在获取到全部的锁之前不会释放持有的锁,这使得线程A与线程B陷入僵持,整个进程处于停滞状态。

2.怎么避免死锁?

减少同步机制中锁的数目,尽量避免同一把锁出现在多处。

九 守护线程

1.用户线程?

一般情况下创建的线程都是用户线程,即该线程未被显式设定为守护线程,未在守护线程内部创建。

2.主线程属于用户线程。

3.什么是守护线程?

运行在后台、为用户线程提供服务的线程。

4.守护线程创建

用户线程调用setDaemon(true)方法,或者在守护线程内部创建线程。

5.守护线程的作用

守护线程用于为用户线程提供服务,如垃圾回收器。

6.JVM在所有的用户线程执行完毕后终止,无论此时守护线程是否执行完毕。

7.守护线程运行在后台,所有用户线程结束后,自动结束。

十 wait与sleep方法对比

1.存在范围

  • wait方法是Object级的,即java中的任何一个对象都拥有该方法,像toString一样。

  • sleep方法只在Thread及其子类中存在。

2.作用

  • sleep使当前线程休眠,释放CPU时间片,不会释放持有的锁。

  • wait用于线程间通信,由对象管理所有以该对象为锁的全部线程。在同步代码中由锁对象调用,使当前线程释放持有的对象锁。

3.使用方法

  • sleep方法是一个静态方法,直接通过Thread调用,Thread.sleep。

  • 用在同步代码中,由锁对象调用。

4.相关方法

  • obj.notify():随机唤醒对象监听器上的一个线程,该线程进入就绪状态,一旦获得对象锁与CPU时间片,从等待处接着执行,不是重新进入run方法或者同步代码中。

  • obj.notifyAll():唤醒对象监听器上所有的等待线程,使它们全部进入就绪状态。

十一 ThreadLocal

1.线程局部变量,为每一个线程提供一个变量的副本,使得各个线程相对独立地操作变量,避免线程安全问题。

2.首先必须明确一点,ThreadLocal.get()获取的变量副本必须手动传入:

ThreadLocal.set(Object obj)
登录后复制

初次获取时,判断线程局部变量中是否保存有变量副本,如果没有则手动传入,在该线程中下次获取的就是初次传入的对象。

3.ThreadLocal的目的是保证在一个线程内部,一次创建,多次获取。

4.基本原理:
      将初次传入的变量与线程绑定,线程不变,变量不变。

十二 GroboUtils多线程测试

   1.JUnit测试不支持多线程,GroboUtils提供了对多线程测试的支持,使用时需要导入架包。

    2.几个比较重要的类:

  • TestRunnable:实现了Runnable接口,run方法中运行的是runTest方法,runTest方法是一个抽象方法。

  • MultiThreadedTestRunner:负责管理并开启多个线程。

    3.测试步骤

⑴继承TestRunnable,实现其中的抽象方法runTest,将需要运行的代码放入该方法中。通常为子类定义一个有参构造方法,方法形参为需要测试的线程,在runTest方法中调用测试线程的run方法,从而将将需要执行的代码注入runTest方法中。

⑵创建测试线程数组,将需要测试的TestRunnable实现类传入其中:

TestRunnable[] tr=new TestRunnable[len];
登录后复制

⑶根据测试线程数组创建线程管理与运行对象并开启多线程:

MultiThreadedTestRunner mttr=new MultiThreadedTestRunner(tr);
mttr.runTestRunnables();
登录后复制

以上是什么是进程与线程?的详细内容。更多信息请关注PHP中文网其他相关文章!

本站声明
本文内容由网友自发贡献,版权归原作者所有,本站不承担相应法律责任。如您发现有涉嫌抄袭侵权的内容,请联系admin@php.cn

热AI工具

Undresser.AI Undress

Undresser.AI Undress

人工智能驱动的应用程序,用于创建逼真的裸体照片

AI Clothes Remover

AI Clothes Remover

用于从照片中去除衣服的在线人工智能工具。

Undress AI Tool

Undress AI Tool

免费脱衣服图片

Clothoff.io

Clothoff.io

AI脱衣机

AI Hentai Generator

AI Hentai Generator

免费生成ai无尽的。

热门文章

R.E.P.O.能量晶体解释及其做什么(黄色晶体)
2 周前 By 尊渡假赌尊渡假赌尊渡假赌
仓库:如何复兴队友
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌
Hello Kitty Island冒险:如何获得巨型种子
1 个月前 By 尊渡假赌尊渡假赌尊渡假赌

热工具

记事本++7.3.1

记事本++7.3.1

好用且免费的代码编辑器

SublimeText3汉化版

SublimeText3汉化版

中文版,非常好用

禅工作室 13.0.1

禅工作室 13.0.1

功能强大的PHP集成开发环境

Dreamweaver CS6

Dreamweaver CS6

视觉化网页开发工具

SublimeText3 Mac版

SublimeText3 Mac版

神级代码编辑软件(SublimeText3)

8核16线程是什么意思? 8核16线程是什么意思? Feb 02, 2023 am 11:26 AM

8核是指CPU有8颗物理核心,16线程是指CPU最多同时可以有16个线程处理任务。核心数和线程数是电脑CPU的重要性能指标,CPU的核心数越高处理速度就越高;线程数越多越有利于同时运行多个程序,因为线程数等同于在某个瞬间CPU能同时并行处理的任务数。多线程可最大限度地实现宽发射、乱序的超标量处理,提高处理器运算部件的利用率,缓和由于数据相关或Cache未命中带来的访问内存延时。

C++并发编程:如何避免线程饥饿和优先级反转? C++并发编程:如何避免线程饥饿和优先级反转? May 06, 2024 pm 05:27 PM

为避免线程饥饿,可以使用公平锁确保资源公平分配,或设置线程优先级。为解决优先级反转,可使用优先级继承,即暂时提高持有资源线程的优先级;或使用锁的提升,即提升需要资源线程的优先级。

C++并发编程:如何进行线程终止和取消? C++并发编程:如何进行线程终止和取消? May 06, 2024 pm 02:12 PM

C++中线程终止和取消机制包括:线程终止:std::thread::join()阻塞当前线程直到目标线程完成执行;std::thread::detach()从线程管理中分离目标线程。线程取消:std::thread::request_termination()请求目标线程终止执行;std::thread::get_id()获取目标线程ID,可与std::terminate()一起使用,立即终止目标线程。实战中,request_termination()允许线程决定终止时机,join()确保在主线

Java错误:JavaFX线程卡顿错误,如何处理和避免 Java错误:JavaFX线程卡顿错误,如何处理和避免 Jun 24, 2023 pm 05:52 PM

在进行JavaFX应用程序开发的过程中,我们常常会遇到JavaFX线程卡顿错误。这种错误的严重程度不同,可能会对程序的稳定性和性能产生不利的影响。为了保证程序的正常运行,我们需要了解JavaFX线程卡顿错误的原因和解决方法,以及如何预防这种错误的发生。一、JavaFX线程卡顿错误的原因JavaFX是一个多线程的UI应用程序框架,它允许程序在后台线程中执行长时

什么是程序运行时指令流的最小单位 什么是程序运行时指令流的最小单位 Aug 23, 2022 pm 02:16 PM

“线程”是程序运行时指令流的最小单位。进程是指一个具有一定独立功能的程序,而线程是进程的一部分,描述指令流执行状态;线程是进程中的指令执行流的最小单位,是CPU调度的基本单位。一个线程是一个任务(一个程序段)的一次执行过程;线程不占有内存空间,它包括在进程的内存空间中。在同一个进程内,多个线程共享进程的资源;一个进程至少有一个线程。

Go语言中线程和进程的区别解析 Go语言中线程和进程的区别解析 Apr 03, 2024 pm 01:39 PM

Go语言中的进程和线程:进程:独立运行的程序实例,拥有自己的资源和地址空间。线程:进程内的执行单元,共享进程资源和地址空间。特点:进程:开销大,隔离性好,独立调度。线程:开销小,共享资源,内部调度。实战案例:进程:隔离长时间运行的任务。线程:并发处理大量数据。

go语言中协程与线程的区别是什么 go语言中协程与线程的区别是什么 Feb 02, 2023 pm 06:10 PM

区别:1、一个线程可以多个协程,一个进程也可以单独拥有多个协程;2、线程是同步机制,而协程则是异步;3、协程能保留上一次调用时的状态,线程不行;4、线程是抢占式,协程是非抢占式的;5、线程是被分割的CPU资源,协程是组织好的代码流程,协程需要线程来承载运行。

Java使用Thread类的stop()函数强制终止线程的执行 Java使用Thread类的stop()函数强制终止线程的执行 Jul 26, 2023 am 09:28 AM

Java使用Thread类的stop()函数强制终止线程的执行在Java多线程编程中,有时候我们需要强制终止一个正在执行的线程。Java提供了Thread类的stop()函数来实现线程的强制终止。本文将介绍stop()函数的用法,并提供代码示例来说明。在介绍stop()函数之前,我们先了解一下Thread类的几个常用方法:start():启动线程,使线程进入

See all articles