今天是线程领域的开篇第一讲。java线程的文章,在网上已经铺天盖地了,但个人觉得线程是一个比较抽象的领域,很多文章没有从根本思维方式上把它具象化,一开始就直接给你从java.util.concurrent包开讲,结果读者被搞得云里雾里,越发觉得线程很神密,很深奥,很难以理解。一些复杂业务的线程运行确实难以琢磨的。但咱们不从业务开讲,咱从概念开讲,解决了概念的问题,线程编程就好办了。
在这一章里,我们提出第一讲的几个最基本的问题,都是初次接触线程时最疑惑的。
1、线程是个啥?
2、创建JAVA Thread
3、为啥要使用线程?
4、为啥使用线程非得要NEW,不NEW不行吗?
5、JAVA两个线程如何通讯?

1、线程是个啥?

在这里多的不唠,少的不说,线程的专业概念,各位另找。你就想像成一个命令就好了。
java应用启动时,最先启动main线程,main线程启动完成后再启动其他业务线程。

2、创建JAVA Thread

最简单开始创建线程有下面两种方式
1.通过继承Thread类创建线程。
2.通过实现Runnable接口创建线程。
其他方式创建线程后面再讲

3、为啥要使用线程?

因为cpu处理数据的速度足够快,其时间都是纳秒级别。如果服务器上的应用不多,那么cpu多数情况下是空闲的,为了充分利用cpu,应当使用线程。

一个简单例子:比如一个业务代码块里需要访问四、五个第三方的接口,并且访问这些接口又不需要先后顺序,同时访问的参数又不是共享参数。那么此时就应当使用线程来访问获取第三方接口数据。
使用方法是每个接口访问启动一个线程,等所有接口访问都获得数据后再进行计算处理。

根据实验数据访问一个http接口平均时间在700至900毫秒间,4-5个接口按顺序执行的得3~4秒时间这是让人无法接受的。如果使用线程时间将缩小到900毫秒以下。
复杂的业务计算代码中使用的线程更多,比如flink框架

4、为啥使用Thread非得要NEW,不NEW不行吗?

通俗的讲多使用一个线程,就相当于另起一个炉灶。比如夫妻快餐小吃店,厨师只有一位就是老板(也可能是老板娘),想提高上菜速度那必须得再加一个厨师,那你不就得new一个咯。所以使用线程非得要NEW,不new不行。new多了也不行,因为小吃店的厨房小啊。

5、JAVA两个线程如何通讯?

package LearnThread.learnthread;
public class MyThread implements Runnable{private Object phone;private MyCounter count;public MyThread(MyCounter count,Object phone) {this.phone = phone;this.count = count;}@Overridepublic void run() {System.out.println("MyThread1开跑前=" + count.getRunNum());for (int i = 0; i < count.getRunNum(); i++) {System.out.println("MyThread1=" + (i+1) + "=" + count.getRunNum());count.setRunNum(count.getRunNum() - 1);try {Thread.sleep(1);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}}package LearnThread.learnthread;
public class MyThread2 implements Runnable{private Object phone;private MyCounter count;public MyThread2(MyCounter count,Object phone) {this.phone = phone;this.count = count;}@Overridepublic void run() {System.out.println("MyThread2开跑前=" + count.getRunNum());for (int i = 0; i < count.getRunNum(); i++) {System.out.println("MyThread2=" + (i+1) + "=" + count.getRunNum());count.setRunNum(count.getRunNum() - 1);try {Thread.sleep(1);} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}}}
}package LearnThread.learnthread;
public class MyCounter {private Integer runNum = 0;public MyCounter(Integer runNum) {this.runNum = runNum;}public void setRunNum(Integer runNum) {this.runNum = runNum;}public Integer getRunNum() {return runNum;}public static void main(String[] args) {MyCounter count = new MyCounter(20);Object phone = new Object();MyThread run1 = new MyThread(count,phone);MyThread2 run2 = new MyThread2(count,phone);Thread thread1 = new Thread(run1);Thread thread2 = new Thread(run2);thread1.start();thread2.start();}
}

执行结果:19,17,15都不见了。此时有人会说:你这代码没加上同步块啊
说得非常好。我在MyThread和MyThread2的run方法加上一样的同步块,如下


增加了同步块,但加锁的都是自己。然并卵,在极端情况下还是会出现如下的结果:13不见了。

原因就是因为两个线程没有建立起有效的通讯。要建立起有效的通讯两个线程同步块必须持有同一个对象,将代码中的synchronized (this) --> synchronized (count) 就解决问题
将MyThread,MyThread2的run方法修改如下,会有什么效果,请看。MyThread的等待时间是100毫秒,MyThread2的等待时间是1毫秒(请自行修改代码)

执行结果
大部份时间是mythread2执行的

               synchronized (count) {count.wait(1);System.out.println("MyThread2=" + (i+1) + "=" + count.getRunNum());count.setRunNum(count.getRunNum() - 1);count.notify();//Thread.sleep(1); }

将Mythread2的count.notify()放开后,执行结果如下

整个时间是交替进行的。再次证明要建立线程间的通讯,各线程应当持有同一对象。
看完这篇基础文章,你应该会对线程概念有个大致的了解,它也不是那么难。

如果你觉得这篇文章对你有用,请给个三赞吧

一起学JAVA线程-JAVA Thread的基础相关推荐

  1. java多线程基础篇(二)java线程常见问题Thread Dump日志分析

    线程常见问题 CPU占用率很高,响应很慢 CPU占用率不高,但响应很慢 线程出现死锁的情况 CPU占用率不高,但响应很慢 有的时候我们会发现CPU占用率不高,系统日志也看不出问题,那么这种情况下,我们 ...

  2. java线程(Thread)的创建与常用方法

    目录 Process与Thread 线程的创建 继承Thread 2. 实现Runnable 3. 实现Callable 通过线程下载图片的例子 实现Runnable接口 抢票的例子: 龟兔赛跑: 实 ...

  3. java线程栅栏_Java 多线程基础 - CyclicBarrier

    我的博客 转载请注明原创出处. 序 java.util.concurrent包里有几个能帮助人们管理相互合作的线程集的类,为多线程常见的应用场景预置了抽象好的类库.在遇到这些应用场景时应该直接重用合适 ...

  4. 【Java线程】Thread Runnable必知必会

    1.Java中线程的创建有两种方式: 通过继承Thread类,重写Thread的run()方法,将线程运行的逻辑放在其中; 通过实现Runnable接口,实例化Thread类; (1).继承Threa ...

  5. java线程池教程_Java基础教程——线程池

    启动新线程,需要和操作系统进行交互,成本比较高. 使用线程池可以提高性能-- 线程池会提前创建大量的空闲线程,随时待命执行线程任务.在执行完了一个任务之后,线程会回到空闲状态,等待执行下一个任务.(这 ...

  6. java线程通信概念_java基础线程总结(线程概念、线程创建方式、线程间通信、线程重要方法)...

    基础篇之<线程> @author :kern ---------------------------------------------------------------- 一:进程:是 ...

  7. 今日只为你狂欢-----JAVA线程总结(零基础入门)

  8. 了解Java线程优先级,更要知道对应操作系统的优先级,不然会踩坑

    Java 多线程系列第 6 篇. 这篇我们来看看 Java 线程的优先级. Java 线程优先级 Thread 类中,使用如下属性来代表优先级. private int priority; 我们可以通 ...

  9. java 线程池面试题

    Java多线程面试问题   1. 进程和线程之间有什么不同?  一个进程是一个独立(self contained)的运行环境,它可以被看作一个程序或者一个应用.而线程是在进程中执行的一个任务.Java ...

  10. 详解Java线程生命周期与状态切换

    前提 最近有点懒散,没什么比较有深度的产出.刚好想重新研读一下JUC线程池的源码实现,在此之前先深入了解一下Java中的线程实现,包括线程的生命周期.状态切换以及线程的上下文切换等等.编写本文的时候, ...

最新文章

  1. shiro(2)-架构与配置
  2. sdut 2139BFS
  3. 几道web前端练习题目
  4. 7-3 旅游规划 (25 分)(C语言实现)
  5. 【LeetCode笔记】20.有效的括号(Java、栈) 21. 合并两个有序链表(Java)
  6. Java定时任务调度工具详解之Timer篇
  7. Python----常用模块1
  8. 删除顽固node_modules
  9. Github使用技巧
  10. python控制风扇_如何使用Python在raspberrypi3上使用GPIO控制风扇?
  11. 怎么在线批量网站打开?
  12. 上海二工大 - 健康日报AutoCheck
  13. caj格式的文件如何转换成Word文档?
  14. vue 子组件调用($emit)父组件方法后父组件方法如何回调子组件方法
  15. 获取某个时间的当月起止时间
  16. Redis数据库相关指令
  17. C#组件系列——又一款Excel处理神器Spire.XLS(一)
  18. 驾考一点通维语版_维语版驾考宝典
  19. ESP32开发三_蓝牙开发
  20. Linux创建自启动服务

热门文章

  1. React初尝试-仿写CNode社区
  2. U盘文件、文件夹不显示却能搜索到 显示U盘文件的解决办法
  3. 【手机上的APP都是用什么编程语言写的】
  4. 撤销 git rebase
  5. git rebase命令实际操作记录
  6. [python] 获取股票信息
  7. Flask-mongoengine分页bug
  8. 服务器名称指示SNI
  9. qml 中英文虚拟键盘
  10. 利用STL中的vector实现“有向有权图”的邻接表表示