范文健康探索娱乐情感热点
投稿投诉
热点动态
科技财经
情感日志
励志美文
娱乐时尚
游戏搞笑
探索旅游
历史星座
健康养生
美丽育儿
范文作文
教案论文
国学影视

Java线程创建与常用方法

  进程与线程进程程序由指令和数据组成,但这些指令要运行,数据要读写,就必须将指令加载至 CPU,数据加载至内存。在指令运行过程中还需要用到磁盘、网络等设备。进程就是用来加载指令、管理内存、管理 IO 的 当一个程序被运行,从磁盘加载这个程序的代码至内存,这时就开启了一个进程 线程一个进程之内可以分为一到多个线程。 一个线程就是一个指令流,将指令流中的一条条指令以一定的顺序交给 CPU 执行 Java 中,线程作为最小调度单位,进程作为资源分配的最小单位。 在 windows 中进程是不活动的,只是作为线程的容器 进程与线程的区别进程基本上相互独立的,而线程存在于进程内,是进程的一个子集 进程拥有共享的资源,如内存空间等,供其内部的线程共享 进程间通信较为复杂同一台计算机的进程通信称为 IPC(Inter-process communication)不同计算机之间的进程通信,需要通过网络,并遵守共同的协议,例如 HTTP 线程通信相对简单,因为它们共享进程内的内存,一个例子是多个线程可以访问同一个共享变量 线程更轻量,线程上下文切换成本一般上要比进程上下文切换低 并行与并发
  单核 cpu 下,线程实际还是  串行执行  的。操作系统中有一个组件叫做任务调度器,将 cpu 的时间片(windows下时间片最小约为 15 毫秒)分给不同的程序使用,只是由于 cpu 在线程间(时间片很短)的切换非常快,人类感觉是  同时运行的  。总结为一句话就是:  微观串行,宏观并行  。一般会将这种  线程轮流使用 CPU  的做法称为并发 (concurrent)
  多核 cpu下,每个  核(core)  都可以调度运行线程,这时候线程可以是并行的。 Java 线程创建和运行线程直接使用 Thread package create; import lombok.extern.slf4j.Slf4j; @Slf4j(topic = "c.ThreadCre") public class ThreadCre { public static void main(String[] args) { Thread t = new Thread(){ @Override public void run() { log.debug("running"); } }; t.start(); log.debug("running"); } } 使用 Runnable 配合 Threadpackage create; import lombok.extern.slf4j.Slf4j; @Slf4j(topic = "c.RunnableCre") public class RunnableCre { public static void main(String[] args) { Runnable r = new Runnable() { @Override public void run() { log.debug("running"); } }; Thread t = new Thread(r,"t2"); t.start(); } } 使用 lambda 方式简化package create; import lombok.extern.slf4j.Slf4j; @Slf4j(topic = "c.RunnableCre") public class RunnableCre { public static void main(String[] args) { Runnable r = () -> { log.debug("running"); }; Thread t = new Thread(r,"t2"); t.start(); } } FutureTask 配合 Threadpackage create; import lombok.extern.slf4j.Slf4j; import java.util.concurrent.Callable; import java.util.concurrent.ExecutionException; import java.util.concurrent.FutureTask; @Slf4j(topic = "c.FutureTaskCre") public class FutureTaskCre { public static void main(String[] args) throws ExecutionException, InterruptedException { FutureTask task = new FutureTask<>(new Callable() { @Override public Integer call() throws Exception { log.debug("running..."); Thread.sleep(1000); return 100; } }); Thread t = new Thread(task,"t1"); t.start(); log.debug("{}",task.get()); } } Thread 与 Runnable 的关系用 Runnable 更容易与线程池等高级 API 配合 用 Runnable 让任务类脱离了 Thread 继承体系,更灵活 线程运行的原理栈与栈帧
  每个线程启动后,虚拟机就会为其分配一块栈内存。 每个栈由多个栈帧(Frame)组成,对应着每次方法调用时所占用的内存 每个线程只能有一个活动栈帧,对应着当前正在执行的那个方法 线程上下文切换
  因为以下一些原因导致 cpu 不再执行当前的线程,转而执行另一个线程的代码 线程的 cpu 时间片用完 垃圾回收 有更高优先级的线程需要运行 线程自己调用了 sleep、yield、wait、join、park、synchronized、lock 等方法
  当 Context Switch 发生时,需要由操作系统保存当前线程的状态,并恢复另一个线程的状态,Java 中对应的概念就是程序计数器(Program Counter Register),它的作用是记住下一条 jvm 指令的执行地址,是线程私有的 状态包括程序计数器、虚拟机栈中每个栈帧的信息,如局部变量、操作数栈、返回地址等 Context Switch 频繁发生会影响性能 常见方法
  方法名
  static
  功能说明
  注意
  start()
  启动一个新线程,在新的线程运行 run 方法中的代码
  start 方法只是让线程进入就绪,里面的代码不一定立刻运行(CPU的时间片还没有分给它)。每个线程对象的 start 方法只能调用一次,否则会出现异常
  run()
  新线程启动后会调用的方法
  如果在构造 Thread 对象时传递了 Runnable 参数,则线程启动后会调用 Runnable 中的 run 方法。但可以创建 Thread 的子类对象来覆盖默认行为
  join()
  等待线程运行结束
  join(long n)
  等待线程运行结果,最多等待 n 毫秒
  getId()
  获取线程长整型的 id
  getName()
  获取线程名
  setName(String)
  修改线程名
  getPriority()
  获取线程优先级
  setPriority(int)
  修改线程优先级
  java中规定线程优先级是1~10 的整数,较大的优先级能提高该线程被 CPU 调度的机率
  getState()
  获取线程状态
  Java 中线程状态是用 6 个 enum 表示,分别为:NEW, RUNNABLE, BLOCKED, WAITING, TIMED_WAITING, TERMINATED
  isInterrupted()
  判断是否被打断
  不会清除 打断标记
  isAlive()
  线程是否存活(还没有运行完毕)
  interrupt()
  打断线程
  如果被打断线程正在 sleep,wait,join 会导致被打断的线程抛出 InterruptedException,并清除 打断标记 ;如果打断的正在运行的线程,则会设置 打断标记 ;park 的线程被打断,也会设置 打断标记
  interrupted()
  static
  判断当前线程是否被打断
  会清除 打断标记
  currentThread()
  static
  获取当前正在执行的线程
  sleep(long n)
  static
  让当前执行的线程休眠 n 毫秒,休眠时让出 CPU 的时间片给其他程序
  yield()
  static
  提示线程调度器让出当前线程对CPU的使用
  主要是为了测试和调试 start 与 run
  调用 run public static void main(String[] args) {  	Thread t1 = new Thread("t1") {  		@Override  		public void run() {  			log.debug(Thread.currentThread().getName());  			FileReader.read(Constants.MP4_FULL_PATH);  		}  	};       	t1.run();  	log.debug("do other things ..."); }
  输出 19:39:14 [main] c.TestStart - main 19:39:14 [main] c.FileReader - read [1.mp4] start ... 19:39:18 [main] c.FileReader - read [1.mp4] end ... cost: 4227 ms 19:39:18 [main] c.TestStart - do other things ...
  程序仍在 main 线程运行, FileReader.read() 方法调用还是同步的
  总结 直接调用 run 是在主线程中执行了 run,没有启动新的线程 使用 start 是启动新的线程,通过新的线程间接执行 run 中的代码 sleep 与 yield
  sleep 调用 sleep 会让当前线程从  Running  进入  Timed Waiting  状态(阻塞) 其它线程可以使用 interrupt 方法打断正在睡眠的线程,这时 sleep 方法会抛出 InterruptedException 睡眠结束后的线程未必会立刻得到执行(抢占时间片) 建议用 TimeUnit 的 sleep 代替 Thread 的 sleep 来获得更好的可读性
  yield 调用 yield 会让当前线程从  Running  进入  Runnable  就绪状态,然后调度执行其它线程 具体的实现依赖于操作系统的任务调度器
  线程优先级 线程优先级会提示(hint)调度器优先调度该线程,但它仅仅是一个提示,调度器可以忽略它 如果 cpu 比较忙,那么优先级高的线程会获得更多的时间片,但 cpu 闲时,优先级几乎没作用 join
  等待一个线程执行结束
  等待多个线程的结果
  情况一: package testJoin;  import lombok.extern.slf4j.Slf4j;  @Slf4j(topic = "c.demo1") public class demo1 {      static int r = 0 , r1 = 0 , r2 = 0;      public static void main(String[] args) throws InterruptedException {         test2();     }      private static void test2() throws InterruptedException {         Thread t1 = new Thread(() -> {             try {                 Thread.sleep(1000);                 r1 = 10;             } catch (InterruptedException e) {                 e.printStackTrace();             }         });         Thread t2 = new Thread(() -> {             try {                 Thread.sleep(2000);                 r1 = 20;             } catch (InterruptedException e) {                 e.printStackTrace();             }         });         long start = System.currentTimeMillis();         t1.start();         t2.start();         log.debug("join begin");         t1.join();         log.debug("t1 join end");         t2.join();         log.debug("t2 join end");         long end = System.currentTimeMillis();         log.debug("r1: {} r2: {} cost: {}",r1,r2,end-start);     } }
  输出: 14:18:02 [main] c.demo1 - join begin 14:18:03 [main] c.demo1 - t1 join end 14:18:04 [main] c.demo1 - t2 join end 14:18:04 [main] c.demo1 - r1: 20 r2: 0 cost: 2008
  情况二: package testJoin;  import lombok.extern.slf4j.Slf4j;  @Slf4j(topic = "c.demo1") public class demo1 {      static int r = 0 , r1 = 0 , r2 = 0;      public static void main(String[] args) throws InterruptedException {         test2();     }      private static void test2() throws InterruptedException {         Thread t1 = new Thread(() -> {             try {                 Thread.sleep(1000);                 r1 = 10;             } catch (InterruptedException e) {                 e.printStackTrace();             }         });         Thread t2 = new Thread(() -> {             try {                 Thread.sleep(2000);                 r1 = 20;             } catch (InterruptedException e) {                 e.printStackTrace();             }         });         long start = System.currentTimeMillis();         t1.start();         t2.start();         log.debug("join begin");         t2.join();         log.debug("t2 join end");         t1.join();         log.debug("t1 join end");         long end = System.currentTimeMillis();         log.debug("r1: {} r2: {} cost: {}",r1,r2,end-start);     } }
  输出: 14:19:19 [main] c.demo1 - join begin 14:19:21 [main] c.demo1 - t2 join end 14:19:21 [main] c.demo1 - t1 join end 14:19:21 [main] c.demo1 - r1: 20 r2: 0 cost: 2006
  另外 join 也可以带参数,是有时效的等待。当到设定时间线程还未给出结果,直接向下运行,不再等待。如果设定时间还没到但是线程已经执行完毕,则直接向下执行,不再等待。 interrupt
  打断 sleep,wait,join 的线程
  这几个方法都会让线程进入阻塞状态
  打断 sleep 的线程, 会清空打断状态,以 sleep 为例 package testInterrupt;  import lombok.extern.slf4j.Slf4j;  @Slf4j(topic = "c.demo1") public class demo1 {     public static void main(String[] args) throws InterruptedException {         Thread t1 = new Thread(() -> {             log.debug("sleep...");             try {                 Thread.sleep(5000);                 //注意:sleep,wait,join等被打断并以异常形式表现出来后                 // 会把打断标记重新置为 false(未打断状态)             } catch (InterruptedException e) {                 e.printStackTrace();             }         },"t1");          t1.start();         Thread.sleep(1000);         log.debug("interrupt");         t1.interrupt();         log.debug("打断标记:{}",t1.isInterrupted());     } }
  输出: 15:08:12 [t1] c.demo1 - sleep... 15:08:13 [main] c.demo1 - interrupt 15:08:13 [main] c.demo1 - 打断标记:false java.lang.InterruptedException: sleep interrupted 	at java.lang.Thread.sleep(Native Method) 	at testInterrupt.demo1.lambda$main$0(demo1.java:11) 	at java.lang.Thread.run(Thread.java:748)  Process finished with exit code 0
  打断正常运行的线程打断标记置为:true package testInterrupt;  import lombok.extern.slf4j.Slf4j;  @Slf4j(topic = "c.demo2") public class demo2 {     public static void main(String[] args) throws InterruptedException {         Thread t1 = new Thread(() -> {             while (true){                 boolean interrupted = Thread.currentThread().isInterrupted();                 if(interrupted){                     log.debug("被打断了,退出循环");                     break;                 }             }         },"t1");         t1.start();          Thread.sleep(1000);         log.debug("interrupt");         t1.interrupt();     } }
  输出: 15:17:40 [main] c.demo2 - interrupt 15:17:40 [t1] c.demo2 - 被打断了,退出循环
  打断 park 线程 package testInterrupt;  import lombok.extern.slf4j.Slf4j;  import java.util.concurrent.locks.LockSupport;  @Slf4j(topic = "c.demo4") public class demo4 {     public static void main(String[] args) throws InterruptedException {         Thread t1 = new Thread(() -> {             log.debug("park...");             LockSupport.park();             log.debug("unpark...");             log.debug("打断状态:{}",Thread.currentThread().isInterrupted());         },"t1");          t1.start();          Thread.sleep(1000);         t1.interrupt();     } }
  输出: 14:16:21 [t1] c.demo4 - park... 14:16:22 [t1] c.demo4 - unpark... 14:16:22 [t1] c.demo4 - 打断状态:true 两阶段终止模式
  package testInterrupt;  import lombok.extern.slf4j.Slf4j;  @Slf4j(topic = "c.demo3") public class demo3 {     public static void main(String[] args) throws InterruptedException {         TwoPhaseTermination tpt = new TwoPhaseTermination();         tpt.start();         Thread.sleep(3500);         tpt.stop();     } }  @Slf4j(topic = "c.TwoPhaseTermination") class TwoPhaseTermination{     private Thread monitor;      //启动监控线程     public void start(){         monitor = new Thread(() -> {             while (true){                 Thread current = Thread.currentThread();                 if(current.isInterrupted()){                     log.debug("料理后事");                     break;                 }                 try {                     Thread.sleep(1000);//情况1                     log.debug("执行监控记录");//情况2                 } catch (InterruptedException e) {                     e.printStackTrace();                     //重新设置打断标记                     current.interrupt();                 }             }         });          monitor.start();     }      //终止监控线程     public void stop(){          monitor.interrupt();     } }
  输出: 15:33:02 [Thread-0] c.TwoPhaseTermination - 执行监控记录 15:33:03 [Thread-0] c.TwoPhaseTermination - 执行监控记录 15:33:04 [Thread-0] c.TwoPhaseTermination - 执行监控记录 java.lang.InterruptedException: sleep interrupted 	at java.lang.Thread.sleep(Native Method) 	at testInterrupt.TwoPhaseTermination.lambda$start$0(demo3.java:29) 	at java.lang.Thread.run(Thread.java:748) 15:33:04 [Thread-0] c.TwoPhaseTermination - 料理后事  Process finished with exit code 0 不推荐的方法
  还有一些不推荐使用的方法,这些方法已过时,容易破坏同步代码块,造成线程死锁
  方法名
  static
  功能说明
  stop()
  停止线程运行
  suspend()
  挂起(暂停)线程运行
  resume()
  恢复线程运行
  来源:https://www.cnblogs.com/lcha-coding/p/16341851.html

曼联vs埃佛顿曼联现在是开始慢慢正轨了。腾大叔想做点成绩。kpi指标得完成。能拿下的比赛必须拿下。埃佛顿除了兰帕德当主帅谁都能有一站之力!他还没把足球理论搞明白。为什么要11个人踢12个行不行。亚洲金融论坛将在港举行逾200位与会者将亲临香港香港贸易发展局副总裁刘会平(左二)与出席新闻发布会的嘉宾合影。香港贸发局摄中新网香港1月6日电(记者魏华都)香港贸易发展局(香港贸发局)6日召开新闻发布会宣布,第16届亚洲金融论坛受不了了!交易总冠军锋线!这一决定也很无奈本来想顺带沾沾冠军的喜庆,没曾想直接砸手里了。猛龙随队记者MichaelGrange爆料,猛龙计划在交易截止日送走波特。上赛季在勇士夺冠后,波特便以2年1240万搭上了多伦多这条船吉布森选秀前的试训后,勒布朗说他很乐意接受骑士选我前NBA球员丹尼尔吉布森近日接受ESPN采访,回忆起他的前骑士队友勒布朗詹姆斯。节选如下另一方面,前骑士后卫丹尼尔吉布森在那个赛季还是个新秀。当被问及与詹姆斯并肩作战的经历时,吉布莫科缺少哈达迪的首场比赛我们转变得不错最后三分钟没坚持住直播吧1月6日讯CBA常规赛,四川7791不敌北京。赛后四川主教练莫科和球员代表袁堂文出席了新闻发布会。莫科点评道今天是缺少内线支柱大哈(哈达迪)的第一场比赛,我认为我们队的转变还莫兰特杰克逊合砍63分,灰熊力克魔术获5连胜灰熊客场123115魔术获得5连胜。莫兰特上来连拿两球,杰伦杰克逊突破上篮,远投三分,而魔术在6分钟只得到4分。哈里斯富尔茨包办魔术前8分,文德尔卡特连得5分,班凯罗突破打进,魔术还记得詹姆斯上一次得分不足10分是什么时候吗?勒布朗詹姆斯以其不可思议的能力而闻名,他能在职业篮球生涯中的任何时刻回忆特定的时刻,无论是几分钟前还是几年前。但本周早些时候,当被问及他周四达到的里程碑时,詹姆斯被难住了。他在常规ampamplt萨克拉门托国王ampampgt你甚至不愿叫我一声绝杀之王篮球比赛中绝杀的定义是球队在最后时刻或接近最后时刻投进了关系胜败的球它的重要之处在于,在比赛接近结束却比分落后对手的情况下,得到反超比分的分数,不给对手留下反超的机会,以此反败为胜骑士对奥科罗仍有信心盼其成为优质摇摆人北京时间1月6日,据雅虎体育记者杰克费舍尔报道,联盟中的消息人士透露,尽管艾萨克奥科罗在职业生涯的第三个赛季仍然没能打出让球队满意的表现,但骑士管理层对他仍有信心,并期待他能成长为烟花的随想吃过晚饭坐在沙发上随意的翻看着手机,忽然屋外传来隆隆的鞭炮声,顺着声音传来的方向,一个箭步跑到窗台边和儿子欣赏着不远处燃放着的烟花,一个个火球冲向夜空,划破了宁静的夜,即使城市里灯云南安宁第一大民企老板17岁崭露头角,十万办厂,年入138。29亿安宁市,云南省直辖县级市,由昆明市代管。位于昆明市西南32千米处,是通往滇西8个地州,并经畹町直接与缅甸相连的交通重镇。地理优越交通发达,320国道直通缅甸,昆安安楚高速,成昆铁路
什么是特发性语言发育障碍?如何应对?干货分享在语言发育迟缓里,有一种类型叫作特发性语言损伤,这些孩子语言发育落后于同龄人,但很奇怪的是,其他方面发育水平似乎没什么异常,无论是智力听力认知理解等都和正常孩子一样。特发性语言发育绘本里泡大的孩子,上学后却不会阅读?根本原因就这2点知乎有一个热度很高的讨论,浏览度高达150多万这个问题,应该也是很多父母的迷思明明从小帮孩子买了读了不少绘本,本以为到了上学的时候,孩子能在阅读上有些优势。可结果事与愿违孩子不仅没问余何适,廓尔亡言,花枝春满,天心月圆学员问昨天晚上孩子完成作业之后还有10分钟关灯睡觉,但他还没洗澡,他就一边洗澡一边看视频。我当时内心是非常煎熬和生气的,躺在床上认真思考了一下,其实这10分钟也没什么大问题,我为什随笔系列六十七熊孩子闯了祸,最好别在大人面前转悠熊孩子这个话题,真的有聊头,这不,话题开始了假期第一天,弟弟一家来我家玩,跟弟弟聊天,聊来聊去,就聊到了孩子,尤其是熊孩子,因为,侄子家的两个孩子很淘气。某人真无耻,说得活像活像地场面失控!河南大宋武侠城免票首日一旅游团拒绝预约强行闯入,有人摔倒在地10月10日,河南开封万岁山大宋武侠城景区免门票第一天大批游客没有预约不顾景区工作人员的阻拦冲进景区大门,场面一度失控。该事件在互联网上引起关注。视频中,大批游客挤在景区大门门口的川渝秘境探访四川乐至报国寺千年树抱佛奇观曾吸引央视走进科学解密报国寺封面新闻记者陈远扬巴蜀文化,源远流长。四川重庆,是我国石窟造像艺术延续时间最长分布最广的地区之一,各具特色的石窟造像遍布巴蜀大地,其中以唐宋年代居多。在资阳市乐至县龙门镇,这国内最坑游客的十条美食街,你踩坑了吗?长沙最好吃的不是火宫殿,而是大学城每所高校附近,总有一条让你堕落的后街。那些汇聚了各种流派小吃的街道,充斥着你学生时代最鲜活的回忆,一帧帧从街头吃到巷尾的记忆碎片,交织成无数段活灵伴手礼买啥?进来抄作业事情是这样的,前不久我有个朋友出差前,跑来问我杭州有啥特色的伴手礼不,我第一反应是龙井,朋友两个字太贵就否了这建议。也是,我自己这个抠搜鬼都没怎么舍得送过人龙井,如果只是意思下,龙世界那么大,我想去看看王宝强曾在电影人在囧途里说过这样一句的话世界那么大,我想去看看。这句话却在一位女教师的辞职信中火爆整个网络。是呀,世界那么大,我想去看看。说出了多少人的心声,因为这是自己想要做却没国内5大怪菜,是当地人的心头爱,外地人却表示不想动筷子人不管走到哪一步,总得找点乐子,想一点办法。是的,美食就是我找的乐子,想的办法!小谈食刻和你一起认真对待吃下的食物!导读一方水土养育一方人,不同的地方饮食也不一样,前些日子去了贵州澳大利亚悉尼迎来解封首日来源人民网澳大利亚频道人民网悉尼10月11日电(李含悦梁雪)经过107天的封城后,澳大利亚悉尼11日起进入初步解封阶段。这意味着餐饮场所理发店健身房商店动物园等公共场所向已完成全部