Java线程知识
线程在多任务处理应用程序中有着至关重要的作用
概念
基本概念
进程:在操作系统中每个独立运行的程序就是一个进程
线程:程序执行的一个顺序执行流(程序的一个运行路径),一个进程至少有一个线程,线程拥有自己的堆栈、计数器和局部变量,多个线程共享所在进程的系统资源
并发:cpu在多个进程之间切换
并行:多个进程在多个不同cpu同时执行
多进程:多进程和多线程是多任务的两种类型,进程间数据块是相互独立的,进程间通过信号、管道等交互。
多线程:在多cpu计算机可以真正物理实现,单核计算机只是逻辑实现,由操作系统进行线程管理调度。
线程生命周期
新建 -> 就绪:start()
就绪 -> 运行:获得处理器资源
运行 -> 就绪:失去处理器资源
运行 -> 终止: 执行完成或者抛出异常,stop方法
运行 -> 阻塞: sleep,IO阻塞,等待同步锁,wait()等待其他线程通知(notify),suspend()挂起
阻塞 -> 就绪: sleep时间到了,IO方法返回,获得同步锁,收到notify()或notifyAll(),resume()恢复
//stop()容易造成死锁(该方法已过时)
Java线程模型
Thread类
继承Thread类,其中run()方法用于执行线程要执行的任务,start()方法用于启动线程
public class Mythread1 extends Thread {
@Override
public void run() {
this.setName("我的线程02");
System.out.println(this.getName());
}
public static void main(String[] args) {
Mythread1 mythread1 = new Mythread1();
mythread1.start();
System.out.println(Thread.currentThread().getName());
}
}
Runnable接口,实现Runnable接口
public class MyThread2 implements Runnable {
@Override
public void run() {
System.out.println("runnable");
}
public static void main(String[] args) {
Thread thread = new Thread(new MyThread2());
thread.start();
}
}
Callable接口,可以返回线程执行的值,通过FutureTask接收,FutureTask实现了RunnableFuture接口,实际上RunnableFuture继承了Runnable和Future接口,特别注意get()方法返回返回值,会造成阻塞
import java.util.concurrent.*;
public class MyCallable implements Callable<String> {
private long waitTime;
public MyCallable(int timeInMillis){
this.waitTime=timeInMillis;
}
@Override
public String call() throws Exception {
Thread.sleep(waitTime);
//return the thread name executing this callable task
return Thread.currentThread().getName();
}
}
class FutureTaskExample {
public static void main(String[] args) {
MyCallable callable1 = new MyCallable(1000); // 要执行的任务
MyCallable callable2 = new MyCallable(2000);
FutureTask<String> futureTask1 = new FutureTask<String>(callable1);// 将Callable写的任务封装到一个由执行者调度的FutureTask对象
FutureTask<String> futureTask2 = new FutureTask<String>(callable2);
ExecutorService executor = Executors.newFixedThreadPool(2); // 创建线程池并返回ExecutorService实例
executor.execute(futureTask1); // 执行任务
executor.execute(futureTask2);
while (true) {
try {
if(futureTask1.isDone() && futureTask2.isDone()){// 两个任务都完成
System.out.println("Done");
executor.shutdown(); // 关闭线程池和服务
return;
}
if(!futureTask1.大专栏 Java线程知识 class="na">isDone()){ // 任务1没有完成,会等待,直到任务完成
System.out.println("FutureTask1 output="+futureTask1.get());
}
System.out.println("Waiting for FutureTask2 to complete");
String s = futureTask2.get(200L, TimeUnit.MILLISECONDS);
if(s !=null){
System.out.println("FutureTask2 output="+s);
}
} catch (InterruptedException | ExecutionException e) {
e.printStackTrace();
}catch(TimeoutException e){
//do nothing
}
}
}
}
线程方法
run()线程执行的内容
start()启动线程
sleep()线程休眠指定时间,不会释放对象锁
isAlive()判断线程是否处于激活状态(就绪或运行)
join()是一个同步方法,父线程等待子线程执行指定时间(若为0则一直等待,直到子线程执行完毕),理解(join(),父线程获得同步代码块,wait一段时间,等待子线程执行完成或时间结束)
public final synchronized void join(long millis)
throws InterruptedException {
long base = System.currentTimeMillis();
long now = 0;
if (millis < 0) {
throw new IllegalArgumentException("timeout value is negative");
}
if (millis == 0) {
while (isAlive()) {
wait(0);
}
} else {
while (isAlive()) {
long delay = millis - now;
if (delay <= 0) {
break;
}
wait(delay);
now = System.currentTimeMillis() - base;
}
}
}
import static java.lang.Thread.currentThread;
import static java.lang.Thread.sleep;
public class TestJoin implements Runnable {
public static void main(String[] sure) throws InterruptedException {
Thread t = new Thread(new TestJoin());
long start = System.currentTimeMillis();
t.start();
t.join(100);//等待线程t 1000毫秒
System.out.println(System.currentTimeMillis()-start);//打印出时间间隔
System.out.println("Main finished");//打印主线程结束
}
@Override
public void run() {
// synchronized (currentThread()) {
for (int i = 1; i <= 5; i++) {
try {
sleep(1000);//睡眠5秒,循环是为了方便输出信息
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("睡眠" + i);
}
System.out.println("TestJoin finished");//t线程结束
}
// }
}
static void yield()暂停线程,并允许其他线程执行
线程优先级
线程优先级只是指获得资源的机会,并不是执行顺序
线程同步
synchronized
小知识
多个线程访问同个对象的同步代码块时,同一时刻只能有一个线程得到执行
一个线程访问一个对象的同步代码块时,其他线程仍可以访问非同步代码块
如果被锁的是类,那么无论new多少实例,同属一个类依然会被锁住,即线程之间通信依旧是同步的
需要注意的时synchronized关键字无法被继承,子类覆盖同步方法时,可以调用父类方法或显式加上关键字
定义接口方法不能使用synchronized,构造函数不能用synchronized,但可以用synchronized代码块
Java线程知识的更多相关文章
- Java线程知识拾遗
知识回顾 进程与线程是常常被提到的两个概念.进程拥有独立的代码段.数据空间,线程共享代码段和数据空间,但有独立的栈空间.线程是操作系统调度的最小单位,通常一个进程会包含一个或多个线程.多线程和多进程都 ...
- Java线程知识:二、锁的简单使用
锁的初步认识 说到锁,相信大家都不陌生,这是我们生活中非常常见的一种东西,它的形状也各式各样.在生活中,我们通常用锁来锁住房子的大门.装宠物的笼子.装衣服的衣柜.以及装着我们一些小秘密的小抽屉.... ...
- java线程基础知识----线程与锁
我们上一章已经谈到java线程的基础知识,我们学习了Thread的基础知识,今天我们开始学习java线程和锁. 1. 首先我们应该了解一下Object类的一些性质以其方法,首先我们知道Object类的 ...
- java线程基础知识----线程基础知识
不知道从什么时候开始,学习知识变成了一个短期记忆的过程,总是容易忘记自己当初学懂的知识(fuck!),不知道是自己没有经常使用还是当初理解的不够深入.今天准备再对java的线程进行一下系统的学习,希望 ...
- java线程基础知识----java daemon线程
java线程是一个运用很广泛的重点知识,我们很有必要了解java的daemon线程. 1.首先我们必须清楚的认识到java的线程分为两类: 用户线程和daemon线程 A. 用户线程: 用户线程可以简 ...
- Java多线程 编写三各类Ticket、SaleWindow、TicketSaleCenter分别代表票信息、售票窗口、售票中心。 售票中心分配一定数量的票,由若干个售票窗口进行出售,利用你所学的线程知识来模拟此售票过程。
package com.swift; import java.util.ArrayList; import java.util.HashMap; import java.util.List; impo ...
- [不得不知道系列]Java线程面试你不得不知道的基础知识一
Java内存管理面试指南一 Java基础面试指南一 Java基础面试指南二 Java基础面试指南三 Java基础面试指南四 Java线程面试指南一 Java线程面试指南二 Redis面试指南一 Kaf ...
- 【Java并发】1. Java线程内存模型JMM及volatile相关知识
Java招聘知识合集:https://www.cnblogs.com/spzmmd/tag/Java招聘知识合集/ 该系列用于汇集Java招聘需要的知识点 JMM 并发编程的三大特性:可见性(vola ...
- Java线程基础知识(状态、共享与协作)
1.基础概念 CPU核心数和线程数的关系 核心数:线程数=1:1 ;使用了超线程技术后---> 1:2 CPU时间片轮转机制 又称RR调度,会导致上下文切换 什么是进程和线程 进程:程序运行资源 ...
随机推荐
- 2019牛客暑期多校训练营(第五场)B.generator 1
传送门:https://ac.nowcoder.com/acm/contest/885/B 题意:给出,由公式 求出 思路:没学过矩阵快速幂.题解说是矩阵快速幂,之后就学了一遍.(可以先去学一下矩阵快 ...
- Windows Boot Manager、Bootmgfw.efi、Bootx64.efi、bcdboot.exe 文件的关系
本教程针对于UEFI启动来叙述的,根据普遍的支持UEFI的机器来叙述. 标题简要说明:Windows Boot Manager --------安装完Windows系统后而出现的启动选项(相关的信息 ...
- iOS 添加view的分类(更加方便的设置view的位置)
点击创建UIView的分类category,这里命名为 PLExtension(为了和下面对应) view分类.h文件 #import <UIKit/UIKit.h> @interface ...
- Patroni 修改配置
Patroni 修改配置 背景 使用 Patroni 部署 postgresql 集群的时候,不能单独修改单点的配置,这里需要通过 Patroni 来修改配置. 修改步骤 1. 修改 postgres ...
- 01 语言基础+高级:1-7 异常与多线程_day05 【异常、线程】
day05 [异常.线程] 主要内容 异常.线程 教学目标 能够辨别程序中异常和错误的区别 说出异常的分类 说出虚拟机处理异常的方式 列举出常见的三个运行期异常 能够使用try...catch关键字处 ...
- php 连接oracle插入多张图片的方法
php连接oracle数据库的时候,其查询.更新.删除数据和MySQL类似,但是增加数据.特别是图片的时候就很不一样,这里面涉及到要创建一个blob对象,用blod对象去保存php图片,下面是当插入多 ...
- django项目班笔记-注册功能
目录 一.用户模型设计 1.用户表字段分析 2.用户模式设计 二.执行迁移 三.图形验证码 四.将图形验证加入到前端文件中 验证码生成源码:https://files.cnblogs.com/file ...
- 线程中start与run方法的主要区别
区别一: 在于当程序调用start方法一个新线程将会被创建,并且在run方法中的代码将会在新线程上运行, 然而在你直接调用run方法的时候, ...
- Java 网址短链接服务原理及解决方案
一.背景 现在在各种圈的产品各种推广地址,由于URL地址过长,不美观.不方便收藏.发布.传播以及各种发文字数限制等问题,微信.微博都在使用短链接技术.最近由于使用的三方的生成.解析短链接服务开始限制使 ...
- 主效应|处理误差 |组间误差|处理效应|随机误差|组内误差|误差|效应分析|方差齐性检验|SSE|SSA|SST|MSE|MSA|F检验|关系系数|完全随机化设计|区组设计|析因分析
8 什么是只考虑主效应的方差分析? 就是不考虑交互效应的方差分析,即认为因素之间是不相互影响的,就是无重复的方差分析. 什么是处理误差 (treatment error).组间误差(between ...