黑马程序员 学习日记(九)
来源:互联网 发布:部落冲突 女巫升级数据 编辑:程序博客网 时间:2024/05/06 04:50
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ----------------------
运行多个线程的时候体会更明显。
Java中的多线程
每一个正在运行的程序称为进程,进程的一个最小运行单元就是线程,也是进程执行命令的一个途径,此途径可以是多个。开头先简单的用自己的语言去概括一下线程,多线程说的就是我们只启动一个程序,但是让它同时做多个事情,至少表面看起来是在处理多个任务。JVM本身在启动时就会启动至少两个线程,一个main主线程,一个垃圾回收机制线程。
1.创建线程
那我们光是看着它自动启动线程是不是不够爽,是不是也得自己来启动一个线程玩玩看呢?想要创建线程,使用Java提供的Thread类,下面是官方文档里提供的内容
创建新执行线程有两种方法。一种方法是将类声明为 Thread
的子类。该子类应重写 Thread
类的 run
方法。接下来可以分配并启动该子类的实例。例如,计算大于某一规定值的质数的线程可以写成:
class PrimeThread extends Thread { long minPrime; PrimeThread(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }
然后,下列代码会创建并启动一个线程:
PrimeThread p = new PrimeThread(143); p.start();
创建线程的另一种方法是声明实现 Runnable
接口的类。该类然后实现 run
方法。然后可以分配该类的实例,在创建 Thread
时作为一个参数来传递并启动。采用这种风格的同一个例子如下所示:
class PrimeRun implements Runnable { long minPrime; PrimeRun(long minPrime) { this.minPrime = minPrime; } public void run() { // compute primes larger than minPrime . . . } }
然后,下列代码会创建并启动一个线程:
PrimeRun p = new PrimeRun(143); new Thread(p).start();
每个线程都有一个标识名,多个线程可以同名。如果线程创建时没有指定标识名,就会为其生成一个新名称。
官方文档给出的内容已经非常详细彻底,我觉得我自己的语言再好也说不出比这个更多的内容了,所以这里就直接借用一下。
2.线程的运行
run()方法里面放着线程要执行的代码,主线程要运行的代码放在main方法里。Thread t = new Thread() ;t.start() ;如果是一个没有覆盖run()方法的线程将会什么都不做,而直接去调用run(),就相当于普通类的调用,仍然是主线程在运行。
class ThreadDemo extends Thread{public void run(){for (int i=0; i<20; i++){System.out.println("another thread is running!");}}}public class Demo { public static void main(String[] args) { ThreadDemo td = new ThreadDemo() ; td.run(); for(int i=0; i<20; i++) { System.out.println("main thread is running"); } }}以上代码,无论执行多少次,输出结果都如下所示:
another thread is running!another thread is running!another thread is running!another thread is running!..another thread is running!main thread is runningmain thread is running..main thread is running而如果是用start()方法去启动线程,两个线程会争抢CPU资源,打印会无顺序的交替进行,且每次运行的顺序都不同。
运行多个线程的时候体会更明显。
class ThreadDemo extends Thread{private String name ;public ThreadDemo(String name){this.name = name ;}public void run(){for (int i=0; i<20; i++){System.out.println(name+ " thread is running!..." + i);}}}public class Demo { public static void main(String[] args) { ThreadDemo td1 = new ThreadDemo("first") ; ThreadDemo td2 = new ThreadDemo("second") ; td1.start(); td2.start(); for(int i=0; i<20; i++) { System.out.println("main thread is running"); } }部分输出结果:
main thread is running
first thread is running!...0
first thread is running!...1
second thread is running!...0
second thread is running!...1
second thread is running!...2
因为线程的顺序是随机的,大家运行的结果跟我的不一样很正常,能看到三个线程交替运行了就足够了。
first thread is running!...0
first thread is running!...1
second thread is running!...0
second thread is running!...1
second thread is running!...2
因为线程的顺序是随机的,大家运行的结果跟我的不一样很正常,能看到三个线程交替运行了就足够了。
其实Thread类本身提供了一个获取线程对象和名称的方法getName(),把打印方法内的name替换为this.getName()就自动打印每一个线程的名字,默认的名字是Thread-编号,编号从0开始。
但你也许仍然想自己命名线程的名字,Thread提供了一个构造方法,所以我们可以这么做:
class ThreadDemo extends Thread{public ThreadDemo(String name){super() ; //实现父类的构造方法}public void run(){for (int i=0; i<20; i++){System.out.println(this.getName()+ " thread is running!..." + i);}}}public class Demo { public static void main(String[] args) { ThreadDemo td1 = new ThreadDemo("first") ; ThreadDemo td2 = new ThreadDemo("second") ; td1.start(); td2.start(); for(int i=0; i<20; i++) { System.out.println("main thread is running"); } }这样就保持了自定义的线程名。
3.关于线程的生命周期
创建线程——运行——(冻结)——结束
线程会经历这几个状态的转换,冻结并不一定会进行,没有人为的操作,自然过程没有冻结。当你想控制一个线程,运行线程一段时间后停一会,你将有两种选择,一个是sleep(),另一个是wait()。
sleep(time)就是睡眠,这个睡眠是定时的,后面加一个毫秒单位的时间(想睡眠5秒就写5000),时间到了自然就醒来了继续运行线程。
wait()就是明确的命令暂停,没有你的指示这个线程就会一直等下去,需要notify()方法去唤醒。所以wait()和notify()是一对好基友,你最好不要残忍的将他们分离。
run()方法结束了这个线程就结束了,正常是无需你额外的操作,但你非要再它运行一半或者它在死循环时枪毙它,执行stop()就可以立即结束线程。
以上都是说的理想状态的运行,实际上我们的电脑一直都在处理多个任务。你的线程经常需要排队。打个比喻,中午时间去食堂打饭,发现人很多,你就开始排队,排到你可以打一个菜,想打第二个菜食堂大妈告诉你再排一次队,这时候你很郁闷,不排了!坐在一边等,等一会发现人少了,赶紧去打饭吧!
线程遇到阻塞但是没有放弃打饭的权利在排队,这个状态没有在运行也不属于冻结更不是结束,处于一个临时状态,冻结就相当于我不排队了,你们谁爱排谁去我放弃了在一边等待,就告诉CPU我不找你 你也别找我。
总结
关于线程我能总结的就这么多,大家可以通过练习模拟火车票售票过程深入理解线程的概念(假设有四个窗口同时售票,票源唯一,现在卖的是同一天同一趟的列车,有一个窗口卖出一个座,其他三个窗口就不能再卖这个座),火车票模拟好了,线程也就都掌握了。
写学习日记,越来越感受到好处,一个是自己进行了复习,一个是有利于自己的编辑总结能力,还有以后忘记了回过头来可以看看,毕竟自己写的东西看起来更舒服。
大家互相学习互相进步
---------------------- ASP.Net+Unity开发、.Net培训、期待与您交流! ---------------------- 0 0
- 黑马程序员 学习日记(九)
- 黑马程序员 学习日记(九)
- 黑马程序员 日记(九)
- 黑马程序员-iOS学习日记(九)Block&Protocol
- 黑马程序员_学习日记九_IO一
- 黑马程序员java学习日记九 面向对象的理解
- 黑马程序员--【学习日记九】——基础加强
- 黑马程序员——java学习日记九
- 黑马程序员--学习日记(九)高新部分java基础加强(二)
- 黑马程序员--学习日记
- 黑马程序员_日记19_Java多线程(九)
- 黑马程序员学习日记----多线程(一)
- 黑马程序员学习日记----多线程(二)
- 黑马程序员-学习日记17( GUI )
- 黑马程序员 学习日记(一)
- 黑马程序员 学习日记(二)
- 黑马程序员 学习日记(三)
- 黑马程序员 学习日记(四)
- poj1458
- js简单的通过点击“上一张”“下一张”图片切换
- 10.装饰模式--Decorator
- 火线冲击游戏iphone版,android版本正式上线
- ADB 通用驱动的实现
- 黑马程序员 学习日记(九)
- GTK 框架(Frames)
- 关于ZendFramework2 no zuo no die的日子
- 2014-07-17 java学习总结
- 11.组合模式--Composite
- WeChall Encodings: URL
- Win7下VMware虚拟机centos不能上网解决方案
- C.3
- Hello CSDN!