前言:

互联网时代已经发展到了现在。从以前只考虑小流量到现在不得不去考虑高并发的问题。扯到了高并发的问题就要扯到线程的问题。你是否问过自己,你真正了解线程吗?还是你只知道一些其他博客里写的使用方法。下面让我们先从线程的一些基础开始讲解并发这一个知识体系。

一、线程是什么?

首先我们要明白线程是什么,下面是我从百度百科摘过来的概念:

线程(英语:thread)是操作系统能够进行运算调度的最小单位。它被包含在进程之中,是进程中的实际运作单位。一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。在Unix System V及SunOS中也被称为轻量进程(lightweight processes),但轻量进程更多指内核线程(kernel thread),而把用户线程(user thread)称为线程。

这个概念比较晦涩难懂,我们可以这样理解线程表示的就是一条单独的执行流,一个程序可以包括很多子任务,而这些子任务就是一条线程。这个线程有自己的程序执行计数器,也有自己的栈。程序就是一个进程。平常我们所说的多线程不是很多个程序在一起运行,那叫多进程。多线程则是一个程序里面很多个任务在同时执行。(注意:通常多线程在OS底层是通过时间片分配来实现多线程的,实际上每一个时间片只运行了一条线程)

二、怎么创建线程?

1、继承Thread

public class StudyThread extendsThread {

@Overridepublic voidrun() {

System.out.println("学习多线程");

}

}

你可以理解run方法就是类似于单线程中的main函数,如果这个线程执行,那么就会从run方法内的第一条语句开始执行到结束。但是线程现在就开始执行了吗?不是的,要让线程启动必须要先创建出StudyThread这个类的对象,而后开始调用start方法。注意:如果我们没有调用start方法,而是直接调用run方法,那你就可以认为只是调用了一个普通方法。程序并没有达到多线程,还是单线程。如果调用了start方法,程序就有了两条执行流,新的执行run方法,旧的就继续执行main函数。

如果是在单CPU的机器上,同一时刻只能有一个线程执行,而多CPU的机器同一时刻就可以有多个线程同时执行。当所有线程执行完后程序才退出。

2、实现Runnable接口

像我们之前说的设计模式,很多设计模式都涉及到继承,但是Java中只支持单线程。所以我们通常不会用上面的方式,而是去实现Runnable接口。

public class StudyRunnable implementsRunnable {

@Overridepublic voidrun() {

System.out.println("hello");

}

}

其余的和继承Thread一样。但是有一点不同的就是

public static voidmain(String[] args) {

Thread studyThread= new Thread(newStudyRunnable());

studyThread.start();

}

我们需要创建一个线程类,并且传Runnable对象进去。说到底我们操作的还是Thread类,不过是将继承去掉罢了。

三、线程有哪些方法和属性?

接下来我们直接看源码来解释

public class Thread implementsRunnable {//线程初始化入口

publicThread(Runnable target) {

init(null, target, "Thread-" + nextThreadNum(), 0);

}//初始化方法

private voidinit(ThreadGroup g, Runnable target, String name,longstackSize) {

init(g, target, name, stackSize,null, true);

}//真正的初始化方法

private voidinit(ThreadGroup g, Runnable target, String name,longstackSize, AccessControlContext acc,booleaninheritThreadLocals) {if (name == null) {throw new NullPointerException("name cannot be null");

}this.name =name;

Thread parent=currentThread();

SecurityManager security=System.getSecurityManager();if (g == null) {/*Determine if it's an applet or not*/

/*If there is a security manager, ask the security manager

what to do.*/

if (security != null) {

g=security.getThreadGroup();

}/*If the security doesn't have a strong opinion of the matter

use the parent thread group.*/

if (g == null) {

g=parent.getThreadGroup();

}

}

g.checkAccess();/** Do we have the required permissions?*/

if (security != null) {if(isCCLOverridden(getClass())) {

security.checkPermission(SUBCLASS_IMPLEMENTATION_PERMISSION);

}

}

g.addUnstarted();this.group =g;this.daemon =parent.isDaemon();this.priority =parent.getPriority();if (security == null ||isCCLOverridden(parent.getClass()))this.contextClassLoader =parent.getContextClassLoader();else

this.contextClassLoader =parent.contextClassLoader;this.inheritedAccessControlContext =acc!= null ?acc : AccessController.getContext();this.target =target;

setPriority(priority);if (inheritThreadLocals && parent.inheritableThreadLocals != null)this.inheritableThreadLocals =ThreadLocal.createInheritedMap(parent.inheritableThreadLocals);/*Stash the specified stack size in case the VM cares*/

this.stackSize =stackSize;/*Set thread ID*/tid=nextThreadID();

}

}

我们注意,在真正的初始化方法中,有以下这些属性会被初始化:

1、Tread类中重要的属性

1.1、name

线程的名字默认是Thread-后跟一个编号,可以使用默认,通过getName方法得到,也可以通过setName方法自定义名字。

1.2、group

所属线程组,一个线程必然有所属线程组。Thread与ThradGroup的关系就像元素与集合的关系。

1.3、daemon

前面我们说过,启动线程就会启动一条单独的执行流,如果整个线程都结束,那么程序就会结束,但是当整个程序只剩下daemon的时候,程序也会退出。daemon线程一般是其他线程的辅助线程,主要作用是负责垃圾回收。

1.4、priority

线程中的优先级,从1到10,优先级逐渐升高,默认为5。操作方法是用getPriority,setPriority

1.5、stackSize

预期堆栈大小,不指定默认为0,0代表忽略这个属性。与平台相关,不建议使用该属性。

2、Tread类中一些重要的方法

2.1、getState()

得到当前线程的线程状态。Thread.State是枚举类型,有NEW(没有调用start的线程状态)、RUNNABLE(调用start后线程在执行run方法且没有阻塞的状态)、BLOCKED(线程被阻塞)、WAITING(线程被阻塞)、TIMED_WAITING(线程被阻塞)、TERMINATED(线程运行结束后的状态) 5种。

2.2、isAlive()

线程被启动后,run方法结束前,线程都是活的。

2.3、sleep(),yield(),join()

上面三个方法都可以让控制线程的执行,sleep是让线程睡眠的方法,yield是告诉操作系统调用该方法的线程不急着执行,可以先让其他线程执行,当然操作系统可能接受yield的建议,也有可能不接受。join方法则是将其他线程中断,让调用该方法的线程先执行完再执行其他线程,如果这个执行的过程中被中断,就会抛出Interrupted-Exception

四、总结

这篇博客只是先简单介绍了一下线程,让我们知道了线程的创建方法,线程初始化的过程,以及线程中一些常用属性和方法。但是这只是Java并发的皮毛。后续会介绍更深入的知识点。

java 线程百科_Java并发——线程介绍相关推荐

  1. java线程安全性_Java并发-线程安全性

    1.什么是线程安全性? 在线程安全性的定义中,最核心的就是正确性.当多线程访问调用某个类时,线程之间不会出现错误的交互,不管运行时线程如何交替执行,并且在主调代码不需要任何同步或协同,这个类都能表现出 ...

  2. java线程属性_Java 并发 线程属性

    Java 并发 线程属性 @author ixenos 线程优先级 1.每当线程调度器有机会选择新线程时,首先选择具有较高优先级的线程 2.默认情况下,一个线程继承它的父线程的优先级 当在一个运行的线 ...

  3. java queue 线程安全_java并发编程之线程安全方法

    线程安全的实现方法,包含如下方式 一, 互斥同步 使用互斥锁的方式. 举个栗子 synchronized,最常用的同步实现方案, ReentrantLock,java并发包中工具,后续介绍. 互斥同步 ...

  4. java线程池_Java 并发编程 线程池源码实战

    作者 | 马启航 杏仁后端工程师.「我头发还多,你们呢?」 一.概述 笔者在网上看了好多的关于线程池原理.源码分析相关的文章,但是说实话,没有一篇让我觉得读完之后豁然开朗,完完全全的明白线程池,要么写 ...

  5. java 并发 线程安全_Java并发教程–线程安全设计

    java 并发 线程安全 在回顾了处理并发程序时的主要风险(例如原子性或可见性 )之后,我们将通过一些类设计来帮助我们防止上述错误. 其中一些设计导致了线程安全对象的构造,从而使我们能够在线程之间安全 ...

  6. java 线程工厂_Java并发编程:Java的四种线程池的使用,以及自定义线程工厂

    引言 通过前面的文章,我们学习了Executor框架中的核心类ThreadPoolExecutor ,对于线程池的核心调度机制有了一定的了解,并且成功使用ThreadPoolExecutor 创建了线 ...

  7. java统计系统线程数_Java并发(八)计算线程池最佳线程数

    目录 一.理论分析 二.实际应用 为了加快程序处理速度,我们会将问题分解成若干个并发执行的任务.并且创建线程池,将任务委派给线程池中的线程,以便使它们可以并发地执行.在高并发的情况下采用线程池,可以有 ...

  8. java 对象 线程安全_JAVA并发编程学习:构造线程安全的对象

    设计线程安全的类 实例限制 当一个对象被另一个对象封装时,所有访问被被封装对象的代码路径就是全部可知的,这相比于让对象可被整个系统访问来说,更容易对代码路径进行分析.将数据封装在对象内部,把对数据的访 ...

  9. java线程池最大线程数_Java并发(八)计算线程池最佳线程数

    目录 一.理论分析 二.实际应用 为了加快程序处理速度,我们会将问题分解成若干个并发执行的任务.并且创建线程池,将任务委派给线程池中的线程,以便使它们可以并发地执行.在高并发的情况下采用线程池,可以有 ...

最新文章

  1. 使用jvisualvm.exe 的Btrace插件监控应用程序
  2. 联想e52进入bios_联想笔记本怎么设置u盘启动|联想笔记本bios设置usb启动步骤
  3. 【LOJ#2507】[CEOI2011]Matching(KMP,树状数组)
  4. 计算机视觉中常见图像扰动方法的Pytorch实现
  5. 程序员如何才算真正的高效编程?
  6. java语言中实现键盘输入_Java程序设计中的键盘输入数据的方法分析
  7. 原生javascript知识点
  8. ArcGIS for Android Runtime100 基本操作(四)——GPS定位
  9. 基于Springboot实现英语在线学习系统
  10. 事件图谱的构建、推理与应用
  11. Java 响应对象详解
  12. 计算机只存在于计算机硬盘上,计算机病毒只存在于计算机硬盘上。
  13. oracle软件工程,.Net软件工程师学用Oracle系列(9):系统函数(上)
  14. 记忆测试系统java代码_JAVA课程设计——记忆测试系统(附源程序).doc
  15. GIC 基础知识介绍 (一)
  16. 高等概率论 Chapter 5. Random Variables on a Countable Space
  17. 008年杀毒软件排行榜以及排行对比图
  18. 显卡Memory Clock上限问题排查实践
  19. 苹果平板不用原装笔可以吗?值得入手的几款ipad触控笔
  20. javascript 一些常用的正则表达式(手机号码,邮箱,整数,身份证号码,车牌号,中文,只能是字母或者数字)

热门文章

  1. 【elasticsearch】ES数据库重建索引 -- Reindex(数据迁移)
  2. 20-10-010-安装-kafka_2.11-1.1.0-单节点测试
  3. Spark Streaming自定义接收器
  4. Docker : 在宿主机查看docker使用cpu、内存、网络、io情况
  5. oracle rodo 查看大小,Exadata — platforma bazodanowa | Oracle Polska
  6. SpringBoot中如何实现全链路调用日志跟踪?这方法才优雅!
  7. jquery设置video的宽度_使用jQuery和CSS自定义HTML5 Video 控件 简单适用
  8. Java基础-通过反射获取类的信息
  9. DBUtils结果集处理
  10. NSLayoutConstraint 使用详解 VFL使用介绍