java线程基础梳理
java线程
概述
- 进程:运行时概念,运行的应用程序,进程间不能共享内存
- 线程:应用程序内并发执行的代码段,可以共享堆内存和方法区内存,而栈内存是独立的。
- 并发理解:在单核机器上,从微观角度来看,一段时间内cup只能执行一个任务,但是因为cup在只执行一段代码段的时候大部分的时间是处于等待程序的,所以可以再开几条程序,然后通过轮询机制,让cpu执行多个进程,从宏观角度来看就是所谓的并发。如果机器是多核,那么就是真正的并发。
线程调度模型
- 线程的调度模型分为: 分时调度模型和抢占式调度模型,Java使用抢占式调度模型
- 分时调度模型: 所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片
- 抢占式调度模型: 优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的CPU时间片相对多一些.
- 线 程 优 先 级 主 要 分 三 种 : MAX_PRIORITY( 最 高 级 );MIN_PRIORITY ( 最 低 级 )NORM_PRIORITY(标准)默认
java 程序的运行原理?
- java 命令会启动 java 虚拟机,启动 JVM,等于启动了一个应用程序,表示启动了一个进程。该进程会自动启动一个“主线程”,然后主线程去调用某个类的 main 方法。所以 main方法运行在主线程中。在此之前的所有程序都是单线程的。
- 一个栈就是一个线程,所谓的并发就是多个不同的栈。
线程创建
- 继承Thread
- 线程编写要继承 java.lang.Thread
- 重写run方法
- 调用的时候调用线程类的start()方法,run方法是让cpu调用的。所以start()方法调用后run方法不会立刻调用。
- 实现runable接口
class CreateRunnable implements Runnable {
@Override
publicvoid run() {
for (inti = 0; i< 10; i++) {
System.out.println("i:" + i);
}
}
}
public class ThreadDemo2 {
publicstaticvoid main(String[] args) {
System.out.println("-----多线程创建开始-----");
// 1.创建一个线程
CreateRunnable createThread = new CreateRunnable();
// 2.开始执行线程 注意 开启线程不是调用run方法,而是start方法
System.out.println("-----多线程创建启动-----");
Thread thread = new Thread(createThread);
thread.start();
}
}
- 使用匿名内部调用
System.out.println("-----多线程创建开始-----");
Thread thread = new Thread(new Runnable() {
public void run() {
for (int i = 0; i< 10; i++) {
System.out.println("i:" + i);
}
}
});
thread.start();
System.out.println("-----多线程创建结束-----");
线程分类
- 主线程、子线程、GC线程
- 一个进程中肯定要有主线程。一般是用main函数来创建
- java主线程结束是不影响子线程的。
- GC线程是守护线程。
- 守护线程随着主线程的销毁而销毁。
- 在一个线程start前用thread.setDaemon(true)可以将用户线程变成守护线程。
- 守护线程和用户线程
- 从线程分类上可以分为:用户线程(以上讲的都是用户线程),另一个是守护线程。
- 其它所有的用户线程结束,则守护线程退出!因为 daemon守护线程是守护非守护线程的
- setDaemon(true) 使线程变成守护线程
- 守护线程一般都是无限执行的.
- 例如 java 中著名的垃圾回收器GC线程就是一个守护线程。
线程安全和锁
- 任何对象都可以是锁,因为锁的本质是参照物,类似于红绿灯,上课铃等等,关键是大家要看一个参照物。
- 同步代码块(以object为锁)
synchronized(object){
[并发逻辑]
}
- 加锁里的逻辑要尽量少
- 同步方法
public synchronized int getTicket(){
}
- 同步方法(非静态)是以当前对象作为锁。
- 如果用非静态同步方法加锁,一般独立出一个对象池,将同步方法放在对象池内,然后多线程对象每次从同一个对象池取资源。
- 同步方法(静态) 是以类作为锁。
线程生命周期


- yield();方法可以让线程方法暂时放弃cpu的抢占,但是一旦放弃后又马上开始抢,有谦让的意义
- Thread.sleep(time) 静态方法 让当前线程休眠time毫秒,不去抢占cpu
- join等到指定的线程执行完后执行
sleep() 与 wait()的比较
- 相同点:wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”
- 不同点:wait()会释放对象的同步锁,而sleep()则不会释放锁
join()方法作用
- 当在主线程当中执行到t1.join()方法时,就认为主线程应该把执行权让给t1
线程死亡
- 有两个原因会导致线程死亡:
- 1) run方法正常退出而自然死亡,
- 2) 一个未捕获的异常终止了run方法而使线程猝死。
- 为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使用isAlive方法。如果是可运行或被阻塞,这个方法返回true; 如果线程仍旧是new状态且不是可运行的, 或者线程死亡了,则返回false.
阻塞状态
- 线程运行过程中,可能由于各种原因进入阻塞状态:
- 1>线程通过调用sleep方法进入睡眠状态;
- 2>线程调用一个在I/O上被阻塞的操作,即该操作在输入输出操作完成之前不会返回到它的调用者;
- 3>线程试图得到一个锁,而该锁正被其他线程持有;
- 4>线程在等待某个触发条件;
参考
java线程基础梳理的更多相关文章
- Java 线程基础
Java 线程基础
- Java线程基础实例
概述 Java线程是一个在实战开发中经常使用的基础功能,而在Java中线程相关的类在java.lang和java.util.concurrent里 Thread package thread.base ...
- Java线程基础知识(状态、共享与协作)
1.基础概念 CPU核心数和线程数的关系 核心数:线程数=1:1 ;使用了超线程技术后---> 1:2 CPU时间片轮转机制 又称RR调度,会导致上下文切换 什么是进程和线程 进程:程序运行资源 ...
- java线程基础知识----线程与锁
我们上一章已经谈到java线程的基础知识,我们学习了Thread的基础知识,今天我们开始学习java线程和锁. 1. 首先我们应该了解一下Object类的一些性质以其方法,首先我们知道Object类的 ...
- java线程基础知识----线程基础知识
不知道从什么时候开始,学习知识变成了一个短期记忆的过程,总是容易忘记自己当初学懂的知识(fuck!),不知道是自己没有经常使用还是当初理解的不够深入.今天准备再对java的线程进行一下系统的学习,希望 ...
- java线程基础巩固---线程生命周期以及start方法源码剖析
上篇中介绍了如何启动一个线程,通过调用start()方法才能创建并使用新线程,并且这个start()是非阻塞的,调用之后立马就返回的,实际上它是线程生命周期环节中的一种,所以这里阐述一下线程的一个完整 ...
- Java 线程基础知识
前言 什么是线程?线程,有时被称为轻量进程(Lightweight Process,LWP),是程序执行流的最小单元.一个标准的线程由线程 ID,当前指令指针 (PC),寄存器集合和堆栈组成.另外,线 ...
- java 线程基础篇,看这一篇就够了。
前言: Java三大基础框架:集合,线程,io基本是开发必用,面试必问的核心内容,今天我们讲讲线程. 想要把线程理解透彻,这需要具备很多方面的知识和经验,本篇主要是关于线程基础包括线程状态和常用方法. ...
- JAVA线程基础
一.线程状态 由于参考的维度不一样,线程状态划分也不一样,我这里简单的分为5大类,并且会说明状态变迁的详细过程:
随机推荐
- 在Linux中执行.sh脚本,异常/bin/sh^M
在Linux中执行.sh脚本,异常/bin/sh^M 在linux中执行.sh脚本,异常/bin/sh^M: bad interpreter: No such file or directory. 分 ...
- 基于python的分治法和例题
分治法 分治法的核心 分:将一个复杂的问题分成两个或更多的相同或相似的子问题,再把子问题分成更小的子问题 治:最后的子问题,可以很容易的直接求解 合:所有子问题的解合并起来就是原问题的解 分治法的特征 ...
- PAC 代理自动发现简介
一 简介 1.1 什么是PAC文件 代理自动配置(PAC)文件包含一组用javaScript编码的规则,允许web浏览器确定是将Web流量直接发送到Internet还是通过代理服务器发送 ...
- C# 字符串与二进制的相互转换
/// <summary> /// 将字符串转成二进制 /// </summary> /// <param name="s"></para ...
- Tangram: Optimized Coarse-Grained Dataflow for Scalable NN Accelerators 阅读笔记
目录 Tangram: Optimized Coarse-Grained Dataflow for Scalable NN Accelerators 1.Abstract 2.Introduction ...
- 用积分方法求K次方和数列公式
这是我很早以前在高中时发现的一个通用计算K次方和数列公式的方法,很特别的地方是用了微积分中的积分方法.目前我还没有发现有谁提出和我一样的方法,如果哪位读者有相关发现,麻烦告知我. 大家很多人都知道高斯 ...
- mysql索引最佳实践
索引最佳实践使用的表CREATE TABLE `employees` ( `id` int(11) NOT NULL AUTO_INCREMENT, `name` varchar(24) NOT ...
- 你真的看懂Android事件分发了吗?
引子 Android事件分发其实是老生常谈了,但是说实话,我觉得很多人都只是懂其大概,模棱两可.本文的目的就是再次从源码层次梳理一下,重点放在ViewGroup的dispatchTouchEvent方 ...
- iOS开发常见问题
1. 在 ViewController 中添加子视图时,导航栏遮挡添加的子视图 let bpView = BpView.init(frame: CGRect.init(x: , y: , width: ...
- java动态代理、Proxy与InvocationHandler
看了好多关于代理的文章,理解和整理一下. 1.代理的基本构成 抽象角色:声明真实对象和代理对象的共同接口,这样可在任何使用真实对象的地方都可以使用代理对象. 代理角色:代理对象内部含有真实对象的引用, ...