Java并发编程想必大家都不陌生,它是实现高并发/高流量的基础,今天我们就来一起学习这方面的内容。

什么是线程?什么是进程?他们之间有什么联系?

简单来说,进程就是程序的一次执行过程,它是系统进行资源分配和调度的基本单位。线程与进程类似,但是线程是更小的执行单位。一个进程在执行过程中可产生多个线程,正因为如此,线程也被称为轻量级的进程 。线程和进程在于进程大多是独立工作的,而各线程则不一定,同一进程下的线程极有可能相互干扰。学习了以上内容,回答第一个问题想必就不在话下了。

Talk is cheap,shou me the code.接下来就让我们通过创建线程,来开启我们的并发之旅吧。

线程的创建

创建线程通常有三种方式,分别为继承 Thread 类(重写run方法),实现Runable接口以及使用FutureTask方式。

继承Thread类

public class MyThread extends Thread {

@Override

public void run() {

System.out.println(Thread.currentThread()+"I am a new thread ");

}

public static void main(String[] args) {

MyThread thread1=new MyThread();

MyThread thread2=new MyThread();

thread1.start();

thread2.start();

}

}

如上述的代码所示,我们继承Thread并且重写了run方法,并开启了两个线程。

该代码执行结果如下:

Thread[Thread-0,5,main]I am a new thread Thread[Thread-1,5,main]I am a new thread

值得一提的是,创建完Thread对象后线程并没有启动,直到调用了start方法才真正启动。

那么问题就来了,我们调用 start() 方法时会执行 run() 方法,为什么我们不能直接调用 run() 方法?

我们new一个Thread,线程就进入了新建状态,而调用了start方法之后它才会进入就绪状态,等待CPU时间片的分配。就绪状态+时间片=线程真正运行,它会自动执行run方法。如果直接调用run方法,main线程会把它当做一个普通的方法去执行,这不是多线程工作(仍然在主线程执行)。

实现Runnable接口

public class MyThread implements Runnable {

@Override

public void run() {

System.out.println(Thread.currentThread() + "I am a new thread ");

}

}

public static void main(String[] args) {

MyThread thread1 = new MyThread();

MyThread thread2 = new MyThread();

new Thread(thread1).start();

new Thread(thread2).start();

}

此代码执行结果和代码一相似,由于Java只支持单继承,如果使用继承Thread的方式就不能再继承其他的类,而Runnable没有这个限制,但是他们有一个共同的缺点,任务没有返回值,我们接着来看最后一种方式。

使用FutureTask

public class CallerTask implements Callable {

@Override

public String call() throws Exception {

return Thread.currentThread() + " hello world";

}

}

public static void main(String[] args) {

FutureTask futureTask1 = new FutureTask<>(new CallerTask());

FutureTask futureTask2 = new FutureTask<>(new CallerTask());

new Thread(futureTask1).start();

new Thread(futureTask2).start();

try {

String result1 = futureTask1.get();

String result2 = futureTask2.get();

System.out.println(result1);

System.out.println(result2);

} catch (InterruptedException e) {

e.printStackTrace();

} catch (ExecutionException e) {

e.printStackTrace();

}

}

该代码执行结果如下:

Thread[Thread-0,5,main] hello world Thread[Thread-1,5,main] hello world

如上述代码所示,我们实现了Callable接口的call()方法,在main函数中创建了两个FurtureTask对象,并且将其启动。通过futureTask.get()方法拿到了我们的返回值。

并发程序的常用方法

wait() 方法

当一个线程调用一个共享变量的wait方法的时候,该线程会被阻塞挂起。如果wait() 方法事先没有获取锁,那么它就会抛出异常。如果发生了以下几种情况,wait状态将会被打破。其他线程调用了该共享对象的notify() 或notifyAll()方法

其他线程调用了该线程的interrupt() 方法

当前线程调用共享对象的wait() 方法的时候,当前线程只会释放当前共享对象的锁,当前线程持有的其他共享对象的锁不会被释放。

notify() 方法

一个线程调用共享对象的notify() 方法之后,会唤醒一个处于等待状态的线程,它并不会确定的唤醒某个线程,而是由JVM决定。被唤醒的线程并不能继续执行,因为它的锁状态已经发生了改变,必须去竞争获取锁,才能进入就绪状态。

notifyAll() 方法

notifyAll()方法会唤醒该共享变量上所有处于等待状态的线程,但是值得注意的是,它只会唤醒调用这个方法之前被阻塞的线程。之后阻塞的它就无能为力了。

sleep方法

调用该方法会暂时让出指定时间的执行权,也就是在此期间不参与CPU的调度,但是该线程所拥有的监视器资源,毕如锁还是持有不让出的。到了指定时间之后,他就会处于就绪状态,等待获取CPU,重新进入运行状态。

接下类我们谈谈sleep()和wait()的联系和区别最重要的一点就是sleep没有释放锁,而wait释放了锁

两者都可以暂停线程的执行

wait()常常用于线程之间的交互/通信

wait() 方法被调用后,线程不会自动苏醒,需要别的线程调用同一个对象上的 notify() 或者 notifyAll() 方法。sleep() 方法执行完成后,线程会自动苏醒。

本篇文章主要介绍了线程的创建以及并发过程的常用方法,希望认真读完的你有所收获。第一:看完点赞,感谢您的认可;

...

第二:随手转发,分享知识,让更多人学习到;

...

第三:记得点关注,每天更新的!!!

java并发编程入门_探讨一下!Java并发编程基础篇一相关推荐

  1. stm32编程入门_电子设计与单片机编程书籍资料推荐

    有些同学让我推荐些入门书籍,尝试写写: 注:请多看下目录与介绍,网络上也有一些读书笔记和推荐,自行判断是否符合现有层次和水平,再决定是否购买. 针对零基础.非专业的电子爱好者,我的推荐学习步骤是: 自 ...

  2. c和java哪个好学_编程入门学习c++和Java哪个比较好

    编程入门学习c++和Java哪个比较好 发布时间:2020-04-25 16:54:41 来源:亿速云 阅读:231 作者:栢白 编程入门学习c++和Java哪个比较好?如今这些都是小白比较关心的,如 ...

  3. java编程学习方法_在线学习Java编程的最佳方法

    java编程学习方法 1.简介 Java是使用最广泛的编程语言之一. 根据Github的最新报告 ,Java被列为仅次于JavaScript的第二大最常用的编程语言. 掌握Java的人有很多话题. 好 ...

  4. java消息幂等性实现_探讨一下实现幂等性的几种方式

    什么是幂等性? 对于同一笔业务操作,不管调用多少次,得到的结果都是一样的. 幂等性设计 我们以对接支付宝充值为例,来分析支付回调接口如何设计? 如果我们系统中对接过支付宝充值功能的,我们需要给支付宝提 ...

  5. java让线程空转_详解Java编程中对线程的中断处理

    1. 引言 当我们点击某个杀毒软件的取消按钮来停止查杀病毒时,当我们在控制台敲入quit命令以结束某个后台服务时--都需要通过一个线程去取消另一个线程正在执行的任务.Java没有提供一种安全直接的方法 ...

  6. 达内java编程 学费_东莞达内Java开发课程学费多少

    众所周知,从编程语言列表开始学习Java是非常困难的.除了科学地选择一种适合自己的编程语言之外,还有入门的方法吗?下面就来说说入门学习java的方法. 学习语言基础 显然,掌握语言基础是步.如果你不知 ...

  7. java forkjoin 简书_浅谈Java的Fork/Join并发框架

    1. Fork/Join是什么 Oracle的官方给出的定义是:Fork/Join框架是一个实现了ExecutorService接口的多线程处理器.它可以把一个大的任务划分为若干个小的任务并发执行,充 ...

  8. java开源线程池_线程池 - Java 并发性和多线程 - UDN开源文档

    线程池 线程池(Thread Pool)对于限制应用程序中同一时刻运行的线程数很有用.因为每启动一个新线程都会有相应的性能开销,每个线程都需要给栈分配一些内存等等. 我们可以把并发执行的任务传递给一个 ...

  9. 阿里云大学 Java编程入门(一)Java语言简介

    Java语言简介 一.Java语言简介 1.1 认识Java(Java发展简介) 1.2 Java语言特点 1.3 Java可移植性 本系列内容为阿里云大学 java学习路线里的内容 阿里云大学 ja ...

最新文章

  1. [UE4]C++实现动态加载的问题
  2. 100W的单词,选择top 10
  3. 编程马拉松大赛试题及代码(C++实现)
  4. python的日志简单使用
  5. 合工大五套卷_2021森哥五套卷(五)
  6. python实现二叉搜索树_python实现二叉查找树
  7. Lnmp环境安装禅道项目管理软件
  8. 机器为内容“体检”?AI算法这样解构内容创作理解
  9. liunx 下压缩解压zip文件
  10. visio付款流程图_visio流程图软件
  11. h5网站服务器配置,h5的web服务器配置
  12. VC-MFC程序设计精讲
  13. 软件工程 -- 数据流图的画法
  14. python花瓣飘零_【动态网页】python3爬取花瓣网图片
  15. 贵港市计算机成绩查询,贵港驾驶证扣分查询
  16. android+特殊符号过滤,android 特殊符号过滤
  17. DBpedia Introduction
  18. 一次ffmpeg -c copy 在avformat_write_header函数处报错:Could not find tag for codec rawvideo in stream #0的原因分析
  19. responsiveSlides 封装好的轮播插件 直接调用
  20. 雷蛇linux识别,雷蛇键盘配置工具 for linux

热门文章

  1. NodeJS获取命令行后面的参数
  2. 【Recat 应用】之 React 脚手架
  3. css基础媒体查询和rem
  4. imp库,python进入import内部
  5. 算法训练营 重编码_关于如何在没有训练营的情况下学习编码的10条提示
  6. matlab编程范例_编程范例到底是什么?
  7. 在vue中实现picker样式_vue vant中picker组件的使用
  8. 导出Oracle数据库字典
  9. jdbc原子事务的实现
  10. matlab将矩阵分解成lu,10行代码实现矩阵的LU分解(matlab)