java ee13_一口气了解多线程及其Java实现

进程:进程就是应用程序在内存中分配的空间,也就是正在运行的程序,各个进程之间不干扰。同时进程保存着程序每一个时刻运行的状态。

程序:用某种编程语言(java、python等)编写,能够完成一定任务或者功能的代码集合,是指令和数据的有序集合,是一段静态代码。

线程:通常一个进程中可以包含若干个线程。进程单独占有一定的内存地址空间,而线程共享所属进程占有的内存地址空间和资源。

在Java中,我们是如何使用多线程的呢?

1.使用Thread 类和 Runnalble 接⼝来实现自己的“线程”类。

// 继承Thread类

public class MyThread1 extends Thread {

@Override

public void run() {

System.out.println("MyThread1*********");

}

}

// 实现Runnable接口

public class MyThread2 implements Runnable {

@Override

public void run() {

System.out.println("MyThread2@@@@@@@@@");

}

}

public class ThreadTest {

public static void main(String[] args) {

Thread myThread1 = new MyThread1();

myThread1.start();

Thread myThread2 = new Thread(new MyThread2());

myThread2.start();

new Thread(new Runnable() {

@Override

public void run() {

System.out.println("MyThread3########");

}

}).start();

new Thread(() -> {

System.out.println("MyThread4%%%%%%%%");

}).start();

}

}

2.我们使用Runnable和Thread来创建一个新的线程。但是他们有一个弊端,就是run方法是没有返回值的。而有时候我们希望开启一个线程去执行一个任务,并且这个任务执行完成之后有一个返回值。JDK提供了Callable接口和Future类为我们解决了这个问题。

public class CallableTask implements Callable {

@Override

public String call() throws Exception {

Thread.sleep(1000);

return "中奖啦~";

}

public static void main(String args[]) throws ExecutionException, InterruptedException {

// 1.使用Future接口

// ExecutorService可以使用submit方法来让⼀个Callable接口执行。

ExecutorService executor1 = Executors.newCachedThreadPool();

CallableTask task = new CallableTask();

Future result = executor1.submit(task);

// 注意调用get方法会阻塞当前线程,直到得到结果。

// 所以实际编码中建议使用可以设置超时时间的重载get方法。

System.out.println(result.get() + "@@");

// 2.使用FutureTask类:FutureTask 是实现的 RunnableFuture 接口的,

// 而 RunnableFuture 接口同时继承了 Runnable 接口和 Future 接口。

ExecutorService executor2 = Executors.newCachedThreadPool();

FutureTask futureTask = new FutureTask<>(new CallableTask());

executor2.submit(futureTask);

System.out.println(futureTask.get() + "**");

}

}

什么是线程组和线程优先级?

1.线程组:每个Thread必然存在于⼀个ThreadGroup中,Thread不能独⽴于ThreadGroup存在。执⾏main()⽅法线程的名字是main,如果在new Thread时没有显式指定,那么默认将⽗线程(当前执⾏new Thread的线程)线程组设置为⾃⼰的线程组。

public class ThreadGroupTest {

public static void main(String[] args) {

Thread testThread1 = new Thread(() -> {

System.out.println("testThread1当前线程组名字:" +

Thread.currentThread().getThreadGroup().getName());

System.out.println("testThread1线程名字:" +

Thread.currentThread().getName());

});

Thread testThread2 = new Thread(() -> {

System.out.println("testThread2当前线程组名字:" +

Thread.currentThread().getThreadGroup().getName());

System.out.println("testThread2线程名字:" +

Thread.currentThread().getName());

});

testThread1.start();

testThread2.start();

System.out.println("执⾏main⽅法线程名字:" + Thread.currentThread().getName());

}

}

输出结果:

执⾏main⽅法线程名字:main

testThread2当前线程组名字:main

testThread2线程名字:Thread-1

testThread1当前线程组名字:main

testThread1线程名字:Thread-0

2.线程优先级:Java中线程优先级可以指定,范围是1~10 。但并不是所有的操作系统都支持10级优先级的划分,Java只是给操作系统一个优先级的参考值,线程最终在操作系统的优先级是多少还是由操作系统决定。通常情况下,⾼优先级的线程将会⽐低优先级的线程有更⾼的⼏率得到执⾏。

public static void main(String[] args) {

Thread a = new Thread();

System.out.println("我是默认线程优先级:"+a.getPriority());

Thread b = new Thread();

b.setPriority(10);

System.out.println("我是设置过的线程优先级:"+b.getPriority());

}

我是默认线程优先级:5

我是设置过的线程优先级:10

线程状态

926ee133e8ed

线程状态转换图

锁与同步

无锁的时候,如下代码中两个线程A、B各自执行:

public class ThreadNoneLock {

static class ThreadA implements Runnable {

@Override

public void run() {

for (int i = 0; i < 100; i++) {

System.out.println("Thread A " + i);

}

}

}

static class ThreadB implements Runnable {

@Override

public void run() {

for (int i = 0; i < 100; i++) {

System.out.println("Thread B " + i);

}

}

}

public static void main(String[] args) {

new Thread(new ThreadA()).start();

new Thread(new ThreadB()).start();

}

}

Thread A 0

Thread A 1

Thread A 2

Thread B 0

Thread B 1

Thread B 2

Thread B 3

...

Thread B 97

Thread B 98

Thread B 99

Thread A 3

Thread A 4

Thread A 5

加锁之后(用synchronized关键字加上了同一个对象锁lock),A线程先执行完,B随后执行:

public class ThreadWithLock {

private static Object lock = new Object();

static class ThreadA implements Runnable {

@Override

public void run() {

synchronized (lock) {

for (int i = 0; i < 100; i++) {

System.out.println("Thread A " + i);

}

}

}

}

static class ThreadB implements Runnable {

@Override

public void run() {

synchronized (lock) {

for (int i = 0; i < 100; i++) {

System.out.println("Thread B " + i);

}

}

}

}

public static void main(String[] args) throws InterruptedException {

new Thread(new ThreadA()).start();

Thread.sleep(10);

new Thread(new ThreadB()).start();

}

}

Thread A 97

Thread A 98

Thread A 99

Thread B 0

Thread B 1

Thread B 2

等待/通知机制

如下例子中,线程A和线程B首先打印出自己需要的东西,然后使用notify()方法叫醒另一个正在等待的线程,然后自己使用wait()方法陷入等待并释放lock锁。

public class WaitAndNotify {

private static Object lock = new Object();

static class ThreadA implements Runnable {

@Override

public void run() {

synchronized (lock) {

for (int i = 0; i < 5; i++) {

try {

System.out.println("Thread A: " + i);

lock.notify();

lock.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

lock.notify();

}

}

}

static class ThreadB implements Runnable {

@Override

public void run() {

synchronized (lock) {

for (int i = 0; i < 5; i++) {

try {

System.out.println("Thread B: " + i);

lock.notify();

lock.wait();

} catch (InterruptedException e) {

e.printStackTrace();

}

}

lock.notify();

}

}

}

public static void main(String[] args) throws InterruptedException {

new Thread(new ThreadA()).start();

Thread.sleep(1000);

new Thread(new ThreadB()).start();

}

}

Thread A: 0

Thread B: 0

Thread A: 1

Thread B: 1

Thread A: 2

Thread B: 2

Thread A: 3

Thread B: 3

Thread A: 4

Thread B: 4

信号量

public class Signal {

/**

* volatile关键字可以保证内存的可见性,如果用volatile关键字声明了一个变量,在一个线程里改变了这个变量值,那其他线程是立马可见更改后的值的。

*/

private static volatile int i = 0;

static class ThreadA implements Runnable {

@Override

public void run() {

while (i < 10) {

if (i % 2 == 0) {

System.out.println("Thread A: "+ i);

synchronized (this) {

i++;

}

}

}

}

}

static class ThreadB implements Runnable {

@Override

public void run() {

while (i < 10) {

if (i % 2 == 1) {

System.out.println("Thread B: " + i);

synchronized (this) {

i++;

}

}

}

}

}

public static void main(String[] args) {

new Thread(new ThreadA()).start();

new Thread(new ThreadB()).start();

}

}

Thread A: 0

Thread B: 1

Thread A: 2

Thread B: 3

Thread A: 4

Thread B: 5

Thread A: 6

Thread B: 7

Thread A: 8

Thread B: 9

ThreadLocal

多线程访问同一个共享变量的时候容易出现并发问题,特别是多个线程对同一个变量进行写入的时候,为了保证线程安全,一般使用者在访问共享变量的时候需要进行额外的同步措施才能保证线程安全性。TreadLocal是除了加锁这种同步方式之外的一种保证规避多线程访问出现线程不安全的方法,当我们在创建一个变量后,如果每个线程对其进行访问的时候访问的都是线程自己的变量这样就不会存在线程不安全的问题了。

线程池

为什么要使用线程池:1.创建/销毁线程需要消耗系统资源,线程池可以复用已创建的线程。2.控制并发的数量。并发数量过多,可能会导致资源消耗过多,从而造成服务器崩溃。3.可以对线程做统一管理。

ThreadPoolExecutor

public class ThreadPoolExecutorTest {

public static void main(String[] args) {

// ThreadPoolExecutor提供了四个构造函数: 1至5; 1至5 + 6; 1至5 + 7; 1至5 + 6 + 7

// 参数一:int corePoolSize 该线程池中核心线程数最大值,线程池新建的时候,如果当前线程总数小于corePoolSize,则新建核心线程,如果超过corePoolSize,则新建的是非核心线程

// 参数二:int maximumPoolSize 该线程池中线程总数最大值

// 参数三:long keepAliveTime 该线程池中非核心线程闲置超时时长

// 参数四:TimeUnit unit keepAliveTime的单位

// 参数五:BlockingQueue workQueue 该线程池中的任务队列,维护着等待执行的Runnable对象。常见类型:

// SynchronousQueue:这个队列接收到任务的时候,会直接提交给线程处理,而不保留它,如果所有线程都在工作怎么办?那就新建一个线程来处理这个任务!所以为了保证不出现的错误,使用这个类型队列的时候,maximumPoolSize一般指定成Integer.MAX_VALUE,即无限大

// LinkedBlockingQueue:这个队列接收到任务的时候,如果当前线程数小于核心线程数,则新建线程(核心线程)处理任务;如果当前线程数等于核心线程数,则进入队列等待。由于这个队列没有最大值限制,即所有超过核心线程数的任务都将被添加到队列中,这也就导致了maximumPoolSize的设定失效,因为总线程数永远不会超过corePoolSize

// ArrayBlockingQueue:可以限定队列的长度,接收到任务的时候,如果没有达到corePoolSize的值,则新建线程(核心线程)执行任务,如果达到了,则入队等候,如果队列已满,则新建线程(非核心线程)执行任务,又如果总线程数到了maximumPoolSize,并且队列也满了,则发生错误

// DelayQueue:队列内元素必须实现Delayed接口,这就意味着你传进去的任务必须先实现Delayed接口。这个队列接收到任务时,首先先入队,只有达到了指定的延时时间,才会执行任务

// 参数六:ThreadFactory threadFactory 给线程起名字

// 参数七:RejectedExecutionHandler handler 异常处理

ThreadFactory threadFactory = new ThreadFactory() {

@Override

public Thread newThread(Runnable r) {

return new Thread(r,"thread name...");

}

};

// lambda表达式写法

// ThreadFactory threadFactory = (Runnable r) -> new Thread(r,"thread name");

ThreadPoolExecutor executor = new ThreadPoolExecutor(5,5,0L, TimeUnit.SECONDS, new LinkedBlockingDeque<>(), threadFactory, new ThreadPoolExecutor.AbortPolicy());

executor.execute(new Runnable() {

@Override

public void run() {

System.out.println("@@@@");

}

});

}

}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/343426.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

apache camel_Apache Camel中的断路器模式

apache camel骆驼通常在分布式环境中用于访问远程资源。 远程服务可能由于各种原因和期间而失败。 对于短时间后暂时不可用且可恢复的服务&#xff0c;重试策略可能会有所帮助。 但是某些服务可能会失败或挂起更长时间&#xff0c;从而使调用应用程序无响应且速度缓慢。 防止级…

【渝粤教育】国家开放大学2018年秋季 0505-22T护理学基础 参考试题

科目编号&#xff1a;0529 座位号&#xff1a; 四川电大2018─2019学年度第一学期期末考试 高级英语阅读&#xff08;1&#xff09;试题 &#xff08;开卷&#xff09; 2019年1月 注 意 事 项 一、 将你的准考证号、学生证号、姓名及分校&#xff08;工作站&#xff09;名称填写…

工业级交换机大致可以分为哪几类?

交换机的用途是非常广泛的&#xff0c;可以这样说&#xff0c;只要是需要联网的地方&#xff0c;基本上都会和交换机相关。我们一般把交换机的使用大致为商用和工业级&#xff0c;商用基本上在公司、单位的办公使用比较常见&#xff0c;今天飞畅科技着重为大家介绍一下工业级交…

【渝粤教育】国家开放大学2018年秋季 0630-22T环境法学 参考试题

科目编号&#xff1a;0633 座位号&#xff1a; 2018-2019学年度第一学期期末考试 化工CAD试题 2019年1月 一、试题一&#xff08;本题50分&#xff09; 设置绘图环境并绘制如下图框标题栏并保存。 二、试题二&#xff08;本题50分&#xff09; 调用图框绘一个平面图形标注…

使用MicroProfile应用隔板和背压

我录制了一段视频&#xff0c;介绍如何使用MicroProfile Fault Tolerance实现隔板和背压。 隔板后面的想法是将应用程序分成几个隔离功能的执行单元。 在企业Java应用程序中&#xff0c;这通常意味着定义多个线程池。 向客户端施加反压将导致向客户端添加有关系统当前压力的信…

【渝粤教育】国家开放大学2018年秋季 0695-21T (1)农业企业经营管理 参考试题

科目编号&#xff1a;[0700] 2018-2019学年度第一学期期末考试 中级会计实务&#xff08;一&#xff09; 评分标准 2019年 1 月 以下给出的是参考答案&#xff0c;请酌情给分。 一、单选题&#xff08;本大题共10小题&#xff0c;每小题3分&#xff0c;共计30分&#xff09; 1…

matlab 形态学 颗粒_数字图像处理Matlab-形态学图像处理(附代码)

这是一篇基于matlab&#xff0c;数字图像处理的形态学研究与实现的文章&#xff0c;希望能对你产生帮助。我还写了一套《数字图像处理》(冈萨雷斯版本)的学习笔记&#xff0c;欢迎关注我的csdn同名主页&#xff0c;一起学习成长~1.Objectives:1&#xff0e;利用 MATLAB 研究二值…

【渝粤教育】国家开放大学2018年秋季 0717-21T社会保障基础 参考试题

科目编号&#xff1a;[0721] 座位号 2018-2019学年度第一学期期末考试 财务管理实务 试题 2019年 1 月 一、单项选则题&#xff08;本大题共10小题&#xff0c;每小题3分&#xff0c;共计30分&#xff09; &#xff08;★请考生务必将答案填入到下面对应序号的答题框中★&…

视频光端机维护三大步骤

视频光端机分为发射端设备和接收端设备&#xff0c;发射端设备和摄像机一样置于室外&#xff0c;工程人员通常是对发射端设备过行维护测试。对于视频光端机的检修工作&#xff0c;我们一般分为三个步骤来进行测试。接下来就由飞畅科技的小编来带大家详细了解下视频光端机维护的…

2021年广东-国家开放大学考试指南(必看)-远程辅助以及微信公众号查题

考前准备工作 一、电脑以及摄像头、浏览器准备 1&#xff1a;一台比较流畅的电脑&#xff0c;这个千万不能马虎&#xff0c;万一考试电脑蓝屏或者卡顿&#xff0c;那是很要命的。 2&#xff1a;摄像头&#xff1a;笔记本有自带的可以用自带的&#xff0c;如果是台式机&#…

java jsonarray 追加_我们如何在Java中将JSONArray添加到JSONObject?

该JSON是用于交换数据的基于文本的格式。它是轻量级的组件&#xff0c;与语言无关。我们还可以将JSONArray添加到JSONObject。我们需要首先将一些项目添加到ArrayList中&#xff0c;并将此列表传递给JSONArray类的put()方法&#xff0c;最后使用put()方法将此数组添加到JSONObj…

内存映射文件 写入 卡住_在Java中使用内存映射文件时检测(写入)失败

内存映射文件 写入 卡住内存映射文件是一个很好的并且经常被忽视的工具。 我不会在这里详细介绍它们的工作方式&#xff08;使用 力 Google Luke&#xff01;&#xff09;&#xff0c;但我将快速总结其优势&#xff1a; 操作系统提供的延迟加载和写入缓存&#xff08;您不必…

飞畅科技——视频光端机用光模块的选型详解

光模块的出现简化了数字视频光端机的设计&#xff0c;我们只要把光模块当作一个具有光电转换功能的部件就可以了。那么针对各种不同的光端机&#xff0c;应该怎样选择相应的光模块呢&#xff1f;接下来就由飞畅科技的小编来为大家详细介绍下视频光端机用光模块的选型&#xff0…

视频监控中的光端机是干什么用的?

现如今&#xff0c;随着社会的进步和经济的发展&#xff0c;人民生活开始富裕&#xff0c;经济宽裕的家庭用户已开始考虑使用监控产品来保护自己&#xff0c;监控已经呈现融入家庭生活的趋势。就数字监控而言&#xff0c;虽然是后起之秀&#xff0c;但依然是现阶段发展趋势。光…

每个Java开发人员都应该知道的10个基本工具

大家好&#xff0c;我们已经到了2019年的第二个月&#xff0c;我相信你们所有人都已经为2019年的学习目标以及如何实现这些目标制定了目标。 我一直在撰写一系列文章&#xff0c;为您提供一些知识&#xff0c;使您可以学习和改进以成为2019年更好的全方位开发人员&#xff0c;例…

java怎么使异常不起作用_java – @Test(expected = Exception.class)对我不起作用,我错过了什么?...

我正在使用sts,但也在命令行上使用mvn clean install.我创建了这个简单的测试作为例子.import org.junit.Test;import junit.framework.TestCase;public class QuickTest extends TestCase {Test(expected Exception.class)public void test() {throwsException();}private vo…

数字非压缩光端机的选购原则

数字非压缩光端机主要应用于高速公路监控领域&#xff0c;可以保证实时性&#xff0c;指的是不经过压缩进行光传输的光端机&#xff0c;是在非压缩光端机基础上利用ADM电分插复用与TDM时分复用技术在一根光纤中实现多点多路&#xff08;最大16个视频点&#xff09;视频传播的光…

spring集成jndi_Spring应用程序与JNDI连接池的集成测试

spring集成jndi我们都知道&#xff0c;无论何时连接到数据库&#xff0c;都需要使用连接池。 所有使用JDBC 4类的现代驱动程序都支持它。 在本文中&#xff0c;我们将概述Spring应用程序中的连接池&#xff0c;以及如何在非JEE环境&#xff08;例如测试&#xff09;中处理相同的…

java构造函数重载继承_Java基础-继承 - 写代码换盆的个人空间 - OSCHINA - 中文开源技术交流社区...

访问权限Java 中有三个访问权限修饰符&#xff1a;private、protected 以及 public&#xff0c;如果不加访问修饰符&#xff0c;表示包级可见。可以对类或类中的成员(字段和方法)加上访问修饰符。类可见表示其它类可以用这个类创建实例对象。成员可见表示其它类可以用这个类的实…

【渝粤教育】21秋期末考试管理会计10171k2

1、下列项目中&#xff0c;变动成本法下计入产品成本的是( )。 &#xff08;2 分&#xff09; A&#xff0e;变动性制造费用 B&#xff0e;变动性管理费用 C&#xff0e;固定性管理费用 D&#xff0e;固定性制造费用 2、将成本中心划分为标准成本中心和费用中心的分类依据是&am…