java线程触发_java线程
线程.
状态
新建状态(New):
当用 new 操作符创建一个线程时, 例如 new Thread(r),线程还没有开始运行,此时
线程处在新建状态。 当一个线程处于新生状态时,程序还没有开始运行线程中的代码
就绪状态(Runnable)
一个新创建的线程并不自动开始运行,要执行线程,必须调用线程的 start()方法。当线
程对象调用 start()方法即启动了线程,start()方法创建线程运行的系统资源,并调度线程运行
run()方法。当 start()方法返回后,线程就处于就绪状态。
处于就绪状态的线程并不一定立即运行 run()方法,线程还必须同其他线程竞争 CPU 时
间,只有获得 CPU 时间才可以运行线程。因为在单 CPU 的计算机系统中,不可能同时运行
多个线程,一个时刻仅有一个线程处于运行状态。因此此时可能有多个线程处于就绪状态。
对多个处于就绪状态的线程是由 Java 运行时系统的线程调度程序(thread scheduler)来调度
的。
运行状态(Running)
当线程获得 CPU 时间后,它才进入运行状态,真正开始执行 run()方法.
阻塞状态(Blocked)
线程运行过程中,可能由于各种原因进入阻塞状态:
1>线程通过调用 sleep 方法进入睡眠状态;
2>线程调用一个在 I/O 上被阻塞的操作,即该操作在输入输出操作完成之前不会返回
到它的调用者;
3>线程试图得到一个锁,而该锁正被其他线程持有;
4>线程在等待某个触发条件;
......
所谓阻塞状态是正在运行的线程没有运行结束,暂时让出 CPU,这时其他处于就绪状
态的线程就可以获得 CPU 时间,进入运行状态。
死亡状态(Dead)
有两个原因会导致线程死亡:
run 方法正常退出而自然死亡,
一个未捕获的异常终止了 run 方法而使线程猝死。
为了确定线程在当前是否存活着(就是要么是可运行的,要么是被阻塞了),需要使
用 isAlive 方法。如果是可运行或被阻塞,这个方法返回 true; 如果线程仍旧是 new 状态
且不是可运行的, 或者线程死亡了,则返回 false
新建线程的方法:
1.继承Thread类实现多线程
run()为线程类的核心方法,相当于主线程的main方法,是每个线程的入口
一个线程调用 两次start()方法将会抛出线程状态异常,也就是的start()只可以被调用一次
class Thread1 extends Thread{
@Override
public void run() {
//迭代 循环
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName()+"__"+i);
}
}
}
public class ThreadTest {
public static void main(String[] args) {
System.out.println("main start: "+Thread.currentThread().getName());
for (int i = 0; i < 10; i++) {
Thread1 thread1 =new Thread1();
thread1.start();//多个跑道 并行
}
//main 不等了
System.out.println(" main end ");
}
}
2通过Runnable接口创建线程类
定义runnable接口的实现类,并重写该接口的run()方法,该run()方法的方法体同样是该线程的线程执行体。
创建 Runnable实现类的实例,并以此实例作为Thread的target来创建Thread对象,该Thread对象才是真正的线程对象。
调用线程对象的start()方法来启动该线程。
public class RunnableThreadTest implements Runnable {
@Override
public void run() {
for (int i = 0; i < 10; i++) {
System.out.println(Thread.currentThread().getName() + "__" + i);
}
}
public static void main(String[] args) {
System.out.println("main start: "+Thread.currentThread().getName());
for (int i = 0; i < 5; i++) {
RunnableThreadTest runnableThreadTest = new RunnableThreadTest();
new Thread(runnableThreadTest,"线程"+i).start();
}
}
}
通过Callable和Future创建线程
创建Callable接口的实现类,并实现call()方法,该call()方法将作为线程执行体,并且有返回值。
public interface Callable
{
V call() throws Exception;
}
创建Callable实现类的实例,使用FutureTask类来包装Callable对象,该FutureTask对象封装了该Callable对象的call()方法的返回值。(FutureTask是一个包装器,它通过接受Callable来创建,它同时实现了Future和Runnable接口。)
使用FutureTask对象作为Thread对象的target创建并启动新线程。
调用FutureTask对象的get()方法来获得子线程执行结束后的返回值
public class CallableThreadTest implements Callable
{
public static void main(String[] args)
{
CallableThreadTest ctt = new CallableThreadTest();
FutureTask ft = new FutureTask<>(ctt);
for(int i = 0;i < 100;i++)
{
log.info(Thread.currentThread().getName()+" 的循环变量i的值"+i);
if(i==20)
{
new Thread(ft,"有返回值的线程").start();
}
}
try
{
log.info("子线程的返回值:"+ft.get());
} catch (InterruptedException e)
{
e.printStackTrace();
} catch (ExecutionException e)
{
e.printStackTrace();
}
}
@Override
public Integer call() throws Exception
{
int i = 0;
for(;i<100;i++)
{
log.info(Thread.currentThread().getName()+" "+i);
}
return i;
}
}
并行参数问题的解决
ThreadLocal (线程本地变量) map
新建ThreadLocal并重写initialValue() 重写initialValue 方法 否者对象为空
调用方法(ThreadLocal定义的变量名)threadLocal.get();
package com.testfan.thread;
import java.util.HashMap;
import java.util.Map;
public class ThreadLocalMapTest {
static ThreadLocal> threadLocal = new ThreadLocal>(){
@Override
protected Map initialValue() {
return new HashMap();
}
};
public static void main(String[] args) {
threadLocal.get().put("1","11");
dosomethings();
new Thread(new Runnable() {
@Override
public void run() {
threadLocal.get().put("1","22");
dosomethings();
}
}).start();
new Thread(new Runnable() {
@Override
public void run() {
threadLocal.get().put("1","33");
dosomethings();
}
}).start();
}
private static void dosomethings() {
System.out.println(Thread.currentThread().getName() + " " +threadLocal.get());
}
}
线程等待问题
线程等待 join
for (int i = 0; i < 10; i++) {
Thread1 thread1 =new Thread1();
thread1.start();//多个跑道 并行
try {
thread1.join();//线程等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
sleep
public static void main(String[] args) {
System.out.println("main start: "+Thread.currentThread().getName());
for (int i = 0; i < 10; i++) {
Thread1 thread1 =new Thread1();
thread1.start();//多个跑道 并行
try {
thread1.sleep(1);;//线程等待
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
线程计数器
public class ThreadDemo2 {
public static void main(String[] args) throws InterruptedException {
final CountDownLatch latch= new CountDownLatch(5);//使用java并发库concurrent
//启用5个线程
for(int i=1;i<=5;i++){
new Thread(new Runnable(){
public void run(){
try {
Thread.sleep(1000);
} catch (Exception e) {
e.printStackTrace();
}
System.out.println("子线程执行!");
latch.countDown();//让latch中的数值减一
}
}).start();
}
//主线程
latch.await();//阻塞当前线程直到latch中数值为零才执行
System.out.println("主线程执行!");
}
}
countDownLatch不可能重新初始化或者修改CountDownLatch对象内部计数器的值,一个线程调用countdown方法happen-before另外一个线程调用await方法
线程池优化
为什么用线程池:
服务器应用程序中经常出现的情况是:单个任务处理的时间很短而请求的数目却是巨大的。
为每个请求创建一个新线程的开销很大;为每个请求创建新线程的服务器在创建和销毁线程上花费的时间和消耗的系统资源要比花在处理实际的用户请求的时间和资源更多。
线程池为线程生命周期开销问题和资源不足问题提供了解决方案
好处:
在请求到达时线程已经存在,所以无意中也消除了线程创建所带来的延迟。这样,就可以立即为请求服务,使应用程序响应更快。而且,通过适当地调整线程池中的线程数目,也就是当请求的数目超过某个阈值时,就强制其它任何新到的请求一直等待,直到获得一个线程来处理为止,从而可以防止资源不足。
线程池的几种方法:
https://www.cnblogs.com/aaron911/p/6213808.html
第一种:定时任务(jenkines的定时任务)
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
实例:
ScheduledExecutorService scheduledThreadPool = Executors.newScheduledThreadPool(5);
scheduledThreadPool.scheduleAtFixedRate(new Runnable() {
@Override
public void run() {
System.out.println("111111");
}
},0,1,TimeUnit.SECONDS);//0代表延时多久 1代表多久执行一次,TimeUnit.SECONDS代表时间单位
第二种:
//可以最大开65536, 短任务
ExecutorService cachedThreadPool = Executors.newCachedThreadPool();
实例:
for (int i = 0; i < 100000; i++) {
final int index = i;
//放了十个线程
cachedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(index+Thread.currentThread().getName());
}
});
}
fixedThreadPool.shutdown();
第三种:
//按照固定的数目
ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);//一次运行3个
实例:
for (int i = 0; i < 100; i++) {
final int index = i;
//放了十个线程
fixedThreadPool.execute(new Runnable() {
public void run() {
System.out.println(index+Thread.currentThread().getName());
}
});
}
fixedThreadPool.shutdown();
第四种:
//默认一个
ExecutorService singleThreadExecutor = Executors.newSingleThreadExecutor();
实例:
for (int i = 0; i < 100; i++) {
final int index = i;
//放了十个线程
singleThreadExecutor.execute(new Runnable() {
public void run() {
System.out.println(index+Thread.currentThread().getName());
}
});
}
fixedThreadPool.shutdown();
java线程触发_java线程相关推荐
- java线程池_Java 线程池 8 大拒绝策略,面试必问!
点击上方 Java后端,选择设为星标 技术博文,及时送达 前言 谈到java的线程池最熟悉的莫过于ExecutorService接口了,jdk1.5新增的java.util.concurrent包下的 ...
- java线程死锁_Java线程死锁–案例研究
java线程死锁 本文将描述从在IBM JVM 1.6上运行的Weblogic 11g生产系统中观察到的最新Java死锁问题的完整根本原因分析. 此案例研究还将证明掌握线程转储分析技能的重要性: 包括 ...
- java多线程抽奖_java 线程池、多线程并发实战(生产者消费者模型 1 vs 10) 附案例源码...
导读 前二天写了一篇<Java 多线程并发编程>点我直达,放国庆,在家闲着没事,继续写剩下的东西,开干! 线程池 为什么要使用线程池 例如web服务器.数据库服务器.文件服务器或邮件服务器 ...
- 线程池 java 新建方式_Java线程池的四种创建方式
Java通过Executors提供四种线程池,分别为: newCachedThreadPool创建一个可缓存线程池,如果线程池长度超过处理需要,可灵活回收空闲线程,若无可回收,则新建线程. newFi ...
- java中我爱你_Java线程学习(转)
编写具有多线程能力的程序经常会用到的方法有: run(),start(),wait(),notify(),notifyAll(),sleep(),yield(),join() 还有一个重要的关键字:s ...
- java 线程状态_JAVA线程漫谈:线程状态与状态转换解析
线程使用方式 JDK线程的顶层抽象是Runnable接口,本质上,线程相关的类都是基于Runnable和Thread实现类实现. JDK API级别有不同的创建线程的方式,但本质是还是基于Runnab ...
- java 线程状态_Java线程为何没有Running状态?我猜你不知道。
作者:国栋原文:https://my.oschina.net/goldenshaw/blog/705397 Java虚拟机层面所暴露给我们的状态,与操作系统底层的线程状态是两个不同层面的事.具体而言, ...
- java线程分类_Java 线程类别
Java 线程类别 守护线程和非守护线程 守护线程和非守护线程之前的唯一区别在于:是否阻止JVM的正常退出. JVM正常退出是与异常退出相对的概念,异常退出如调用System.exit(status) ...
- java runnable 异常_JAVA 线程中的异常捕获
在java多线程程序中,所有线程都不允许抛出未捕获的checked exception(比如sleep时的InterruptedException),也就是说各个线程需要自己把自己的checked e ...
最新文章
- linux系统安装nginx步骤,虚拟机(linux)下安装nginx的步骤教程
- DeprecationWarning Mongoose mpromise (mongoose's default promise li
- mysql 用户已设置密码,但登录可以不填密码
- jQuery的DOM操作之取值/赋值(1)
- C#序列化和反序列化
- restlet_Restlet框架– Hello World示例
- mysql 占用swap_查看swap占用情况
- 管理磁盘文件系统(三)
- Oracle SQL的优化 【转】
- 2.2 PHP7.2 狐教程-【PHP变量】
- python发送邮件的模块_python Email 邮件发送模块
- fiddler4安装教程以及手机下载证书时报错 no root certificate was found解决方法
- winrar压缩软件弹出广告解决办法
- 传说中的世界500强面试题-推理能力(2)
- 【精华】PS十大抠图技法(上)
- pycharm收费版和 免费版的区别
- cc2530协调器向终端发信息
- Microsoft Office2010每次打开都提示激活向导
- linux sdl windows.h,SDL入门教程(十):1、多语言支持,Win32下的GetText
- 在三层交换机上配置Trunk并指定接口封装为802.1q