java并发基础及原理
一 java线程用法
1.1 线程使用方式
1.1.1 继承Thread类
继承Thread类的方式,无返回值,且由于java不支持多继承,继承Thread类后,无法再继承其他类。
/**
* 继承Thread类的方式创建线程
*/
public class ThreadExtendTest extends Thread{ @Override
public void run() {
System.out.println("create thread by thread extend");
} public static void main(String[] args) {
new ThreadExtendTest().start();
} }
1.1.2 实现Runnable接口
无返回值,但由于实现的是接口,可以继承其他类。
/**
* 实现Runnable接口的方式创建线程,无返回值
*/
public class ThreadRunnableTest implements Runnable{
@Override
public void run() {
System.out.println("create thread by runnable implements");
} public static void main(String[] args) {
new Thread(new ThreadRunnableTest()).start();
}
}
1.1.3 实现Callable接口
有返回值,且可以继承其他类。
/**
* 实现Callable接口,和FutureTask结合,创建线程,有返回值
*/
public class ThreadCallableTest implements Callable<String> {
@Override
public String call() throws Exception {
return "create thread by implements Callable";
} public static void main(String[] args) throws ExecutionException, InterruptedException{
FutureTask<String> future1 = new FutureTask<String>(new ThreadCallableTest());
Thread thread1 = new Thread(future1);
thread1.start();
System.out.println(future1.get());
}
}
1.1.4 Runnable或Callable和Future结合的线程池方式
/**
* 线程池的方式使用线程
*/
public class ThreadPoolTest implements Callable<String> {
@Override
public String call() throws Exception {
return "create thread by thread pool";
} public static void main(String[] args) throws ExecutionException, InterruptedException{
ExecutorService executorService = Executors.newFixedThreadPool(1);
Future<String> future1 = executorService.submit(new ThreadPoolTest());
System.out.println(future1.get());
executorService.shutdown();
}
}
java线程的四种用法,本质其实分为两类,一个是继承方式,一个是实现接口方式,由于java只支持单继承,继承Thread类后,不能再继承其他类,而使用实现接口的方式,还可以再继承其它有用的类。Runnable方式无返回值,Callable用于需要返回值的场景。利用线程池创建线程,实际上依然是借助Runnable或者Callable。
1.2 线程状态
- ps -aux | grep java查看进程pid,如图1.2。
- top -Hp pid,查看进程各线程cpu、内存等占用情况,如图1.3。
- jstack pid,查看进程各线程的堆栈信息,包括运行状态等,如图1.4。
1.3 安全终止线程
1.3.1 volatile变量+轮询
/**
* volatile变量+轮询安全终止线程
*/
class VolatileThread implements Runnable{
private volatile boolean cancelled;
@Override
public void run() {
while(!cancelled){
System.out.println("VolatileThread");
}
System.out.println("thread stop by volatile variable");
}
public void cancel() { cancelled = true; }
}
1.3.2 中断+轮询
//中断+轮询安全终止线程
class InterruptThread implements Runnable{
@Override
public void run() {
while(!Thread.currentThread().isInterrupted()){
System.out.println("InterruptThread");
}
System.out.println("thread stop by interrupt thread");
} }
1.4 线程通信
1.4.1 等待通知机制
- 获取对象锁
- 如果条件不满足,调用对象wait方法,被通知后仍要检查条件
- 条件满足则执行对应的逻辑
- 获得对象的锁。
- 改变条件。
- 通知所有等待在对象上的线程。
/**
* 线程通信,等待/通知机制
*/
public class ThreadCommunication {
public static void main(String[] args) {
final Object lock = new Object(); new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread A is waiting to get lock");
synchronized (lock) {
try {
System.out.println("thread A get lock");
TimeUnit.SECONDS.sleep(1);
System.out.println("thread A do wait method");
lock.wait();
System.out.println("thread A wait end");
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}).start(); new Thread(new Runnable() {
@Override
public void run() {
System.out.println("thread B is waiting to get lock");
synchronized (lock) {
System.out.println("thread B get lock");
try {
TimeUnit.SECONDS.sleep(5);
} catch (InterruptedException e) {
e.printStackTrace();
}
lock.notify();
System.out.println("thread B do notify method");
}
}
}).start(); }
}
1.4.2 wait/notify底层实现
二 java线程常用方法含义及原理
2.1 daemon线程
2.2 join方法
thread.join()方法,会等待其它线程thread执行完,继续执行当前线程。join方法源码如下:
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;
}
}
}
2.3 sleep()方法
#include <stdio.h>
#include <stdlib.h>
#include <signal.h>
#include <unistd.h>
///时钟编程 alarm()
void wakeUp()
{
printf("please wakeup!!/n");
}
int main(void)
{
printf("you have 4 s sleep!/n");
signal(SIGALRM,wakeUp);
alarm();
//将进程挂起
pause();
printf("good morning!/n");
return EXIT_SUCCESS;
}
2.4 yield()方法
2.5 ThreadLocal用法及源码解析
public T get() {
Thread t = Thread.currentThread();
ThreadLocalMap map = getMap(t);//返回线程内部变量t.threadLocals
if (map != null) {
ThreadLocalMap.Entry e = map.getEntry(this);
if (e != null) {
@SuppressWarnings("unchecked")
T result = (T)e.value;
return result;
}
}
return setInitialValue();//调用t.threadLocals = new ThreadLocalMap(this, firstValue);
}
参考文献
java并发基础及原理的更多相关文章
- Java 并发基础
Java 并发基础 标签 : Java基础 线程简述 线程是进程的执行部分,用来完成一定的任务; 线程拥有自己的堆栈,程序计数器和自己的局部变量,但不拥有系统资源, 他与其他线程共享父进程的共享资源及 ...
- Java并发-volatile的原理及用法
Java并发-volatile的原理及用法 volatile属性:可见性.保证有序性.不保证原子性.一.volatile可见性 在Java的内存中所有的变量都存在主内存中,每个线程有单独CPU缓存内存 ...
- java并发基础(五)--- 线程池的使用
第8章介绍的是线程池的使用,直接进入正题. 一.线程饥饿死锁和饱和策略 1.线程饥饿死锁 在线程池中,如果任务依赖其他任务,那么可能产生死锁.举个极端的例子,在单线程的Executor中,如果一个任务 ...
- java并发基础(二)
<java并发编程实战>终于读完4-7章了,感触很深,但是有些东西还没有吃透,先把已经理解的整理一下.java并发基础(一)是对前3章的总结.这里总结一下第4.5章的东西. 一.java监 ...
- Java并发基础概念
Java并发基础概念 线程和进程 线程和进程都能实现并发,在java编程领域,线程是实现并发的主要方式 每个进程都有独立的运行环境,内存空间.进程的通信需要通过,pipline或者socket 线程共 ...
- 【搞定 Java 并发面试】面试最常问的 Java 并发基础常见面试题总结!
本文为 SnailClimb 的原创,目前已经收录自我开源的 JavaGuide 中(61.5 k Star![Java学习+面试指南] 一份涵盖大部分Java程序员所需要掌握的核心知识.欢迎 Sta ...
- Java并发——volatile的原理
111 Java并发——volatile的原理
- Java 并发编程-不懂原理多吃亏(送书福利)
作者 | 加多 关注阿里巴巴云原生公众号,后台回复关键字"并发",即可参与送书抽奖!** 导读:并发编程与 Java 中其他知识点相比较而言学习门槛较高,从而导致很多人望而却步.但 ...
- Java并发基础框架AbstractQueuedSynchronizer初探(ReentrantLock的实现分析)
AbstractQueuedSynchronizer是实现Java并发类库的一个基础框架,Java中的各种锁(RenentrantLock, ReentrantReadWriteLock)以及同步工具 ...
随机推荐
- MapReduce案例运行及分词
首先查询进程,发现hadoop并没有启动 如何配置hadoop,参考我的另外一篇博文<Hadoop环境准备> 接下来,启动hadoop start-all.sh 或者 start-dfs. ...
- spring cloud config使用mysql存储配置文件
spring cloud config使用mysql存储配置文件 1.结构图 2.pom.xml: <?xml version="1.0" encoding="UT ...
- Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵动态限流规则
Spring Cloud Alibaba | Sentinel:分布式系统的流量防卫兵动态限流规则 前面几篇文章较为详细的介绍了Sentinel的使用姿势,还没看过的小伙伴可以访问以下链接查看: &l ...
- FreeSql (二十七)将已写好的 SQL 语句,与实体类映射进行二次查询
有时候,我们希望将写好的 sql 语句,甚至是存储过程进行查询,虽然效率不高(有时候并不是效率至上). 巧用AsTable var sql = fsql.Select<UserX>() . ...
- 【学习笔记】第一章 python安全开发简介
1.1为什么黑客喜欢用python? python为我们提供了非常完善的基础代码库,覆盖了网络.文件.GUI.数据库.文本等大量内容,被形象的称为“”内置电池“”,用python开发,许多功能不必从零 ...
- TestNG(十) 依赖测试
package com.course.testng.suite; import org.testng.annotations.Test; public class DepenTest { @Test ...
- Nginx缓存原理及机制
文章原创于公众号:程序猿周先森.本平台不定时更新,喜欢我的文章,欢迎关注我的微信公众号. 上篇文章介绍了Nginx一个较为重要的知识点:Nginx实现接口限流.本篇文章将介绍Nginx另一个重要知识点 ...
- [Design Patterns] 03. Behavioral Patterns - Observer Pattern
前言 参考资源 Ref: 史上最全设计模式导学目录(完整版) 观察者模式-Observer Pattern[学习难度:★★★☆☆,使用频率:★★★★★] 对象间的联动——观察者模式(一):多人联机对战 ...
- eclipse中xml文件格式化
eclipse中xml文件格式化(ctrl+shift+f),可能会发现格式化xml文件后很乱,如图: 这不是我想要的样子,我想要的是这样的: 解决办法:windows -> Perferenc ...
- 转:sqlserver 存储毫秒23:59:59.999变成第二天00:00:00.000
因为,在SQL SERVER中DATETIME表示的时间为00:00:00到23:59:59.997,它的时间精度为1/300秒,在使用时会舍入到舍入到 .000..003 或 .007 秒三个增量. ...