Java Thread
来源:互联网 发布:逆袭网络剧第一集 编辑:程序博客网 时间:2024/06/06 07:15
本文章转自博主https://originals-tz.github.io/
0x00 基本概念
使用多线程的目的在于更好地利用CPU资源
介绍一些概念:
- 多线程:指的是这个程序(一个进程)运行时产生了不止一个线程
并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。
并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。
线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果,反过来,线程不安全就意味着线程的调度顺序会影响最终结果
同步:同步就是协同步调,按预定的先后次序进行运行。
0x01 Java的进程状态
新建状态(New):当线程对象对创建后,即进入了新建状态,如:Thread t = new MyThread();
就绪状态(Runnable):当调用线程对象的start()方法(t.start();),线程即进入就绪状态。处于就绪状态的线程,只是说明此线程已经做好了准备,随时等待CPU调度执行,并不是说执行了t.start()此线程立即就会执行;
运行状态(Running):当CPU开始调度处于就绪状态的线程时,此时线程才得以真正执行,即进入到运行状态。注:就绪状态是进入到运行状态的唯一入口,也就是说,线程要想进入运行状态执行,首先必须处于就绪状态中;
阻塞状态(Blocked):处于运行状态中的线程由于某种原因,暂时放弃对CPU的使用权,停止执行,此时进入阻塞状态,直到其进入到就绪状态,才 有机会再次被CPU调用以进入到运行状态。根据阻塞产生的原因不同,阻塞状态又可以分为三种:
1.等待阻塞:运行状态中的线程执行wait()方法,使本线程进入到等待阻塞状态;
2.同步阻塞 – 线程在获取synchronized同步锁失败(因为锁被其它线程所占用),它会进入同步阻塞状态;
3.其他阻塞 – 通过调用线程的sleep()或join()或发出了I/O请求时,线程会进入到阻塞状态。当sleep()状态超时、join()等待线程终止或者超时、或者I/O处理完毕时,线程重新转入就绪状态。
死亡状态(Dead):线程执行完了或者因异常退出了run()方法,该线程结束生命周期。
0x02 Java的多进程创建
1.继承Thread类,重写run()
第一个Test,两个线程输出数字,每输出一个暂停3ms
code
class Test1 extends Thread{ private String name; public Test1(String id) { name = id; } public void run(){ for(int i = 0; i < 5; i++) { System.out.println(name + ":" + i); try { sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } } public static void main(String[] args) { Test1 a = new Test1("thread 1"); Test1 b = new Test1("thread 2"); a.start(); b.start(); }}
output
thread 2:0thread 1:0thread 1:1thread 2:1thread 2:2thread 1:2thread 1:3thread 2:3thread 1:4thread 2:4
可以发现输出的结果是乱序的
2.实现Runnable接口,重写该接口的run()方法
code
class Test2 implements Runnable{ private int number = 10; private String name; public Test2(String n) { name = n; } @Override public void run() { while (number > 0) { number--; System.out.println(name+":number:"+number); try { Thread.sleep(2); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(name + " : zero!"); } public static void main(String[] args) { Test2 b = new Test2("thread"); new Thread(b).start(); new Thread(b).start(); }}
output
thread:number:8thread:number:8thread:number:7thread:number:6thread:number:5thread:number:4thread:number:3thread:number:2thread:number:0thread:number:0thread : zero!thread : zero!
2.9.Thread 和 Runnable
使用Runnable可以:
- 避免点继承的局限,一个类可以继承多个接口。
- 适合于资源的共享:用Thread实现Test2,会发现不能对同一个资源进行操作
- Thread也是Runnable接口的子类
在使用Thread的时候只需要new一个实例出来,调用start()方法即可以启动一个线程。
Thread Test = new Thread();Test.start();
在使用Runnable的时候需要先new一个继承Runnable的实例,之后用子类Thread调用。
Test impelements RunnableTest t = new Test();Thread test = new Thread(t);
在使用Runnable定义的子类中没有start()方法,只有Thread类中才有。
3.互斥访问
在Test2
中,我们对同一个资源进行操作
考虑这种情况
Thread1.Number--Thread2.Number--Thread1.Print NumberThread2.Print Number
原本Thread1.Print Number
输出的是Thread1.Number--
之后的数值
但是按照上述顺序,Thread1.Print Number
输出的是Thread1.Number--
和Thread2.Number--
之后的数值,导致输出结果错误
因此,对于这种情况(多个线程对一个资源进行操作),必须要上锁
mylock.lock();number--;System.out.println(name+":number:"+number);mylock.unlock();
- Thread & Java
- Java Thread
- java Thread
- Java Thread
- Java Thread
- java thread
- Java Thread
- Java Thread
- Java Thread
- java thread
- Java Thread
- java thread
- java thread
- java Thread
- java thread
- java thread
- Java Thread
- Java Thread
- 21_IO流
- java.lang.ClassNotFoundException: org.apache.xbean.spring.context.v2.XBeanNamespaceHandler
- win7与ubuntu14.04双系统下修改默认启动项
- LaTex(PART VIII)文档类和页面布局相关
- 22_IO流
- Java Thread
- [Python 实战]
- 铁路(栈)
- cocos2d-x 之TableView
- 调整linux内核尽量用内存,而不用swap
- HADOOP1.X中HDFS工作原理
- 23_File类递归练习
- 习题3.1(2)
- 统计每年每月的信息