黑马程序员全套Java教程_Java基础教程_多线程之实现多线程(三十四)
1.1 进程
是正在运行的程序 是系统进行资源分配和调用的独立单位; 每一个进程都有它自己的内存空间和系统资源。
1.2 线程
是进程中的单个顺序控制流,是一条执行路径 单线程:一个进程如果只有一条执行路径,则称为单线程程序; 多线程:一个进程如果有多条执行路径,则称为多线程程序; 如记事本中对文本属性进行设置和编辑两个线程不能同时进行,此为单线程;而扫雷中计时和游戏可以同时进行,此为多线程。
1.3 多线程的实现方式1
方式1:继承Thread类 (1)定义一个类MyThread类继承Thread类; (2)在MyThread类中重写run()方法; (3)创建MyThread类的对象; (4)启动线程。 为什么要重写run()? 因为run()是用来封装被形成执行的代码。(MyThread类中可能有其他的代码,但并不是所有的代码都要被线程执行的,为了区分哪些代码是能够被线程执行的,Java提供run()让我们封装被线程执行的代码) run()和start()方法的区别? (1)run():封装线程执行的代码,直接调用,相当于普通方法的调用; (2)start():启动线程,然后由JVM调用此线程的run()方法。
public class MyThread extends Thread {
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( i) ;
}
}
}
public static void main ( String [ ] args) {
MyThread my1 = new MyThread ( ) ;
MyThread my2 = new MyThread ( ) ;
my1. start ( ) ;
my2. start ( ) ;
}
1.4 设置和获取线程名称
前面我们已经实现了多线程的程序并且把数据在控制台输出了,但是我们并不知道这些数据是哪个线程的,所以我们要学习设置和获取线程名称。为此,Thread类提供了两个方法: (1)void setName(String name):将此线程的名称更改为name; (2)String getName():返回此线程的名称; (3)通过构造方法也可以设置线程名称。 获取main()所在的线程名称:public static Thread currentThread(),获取对当前正在执行的线程对象的引用。
public class MyThread extends Thread {
public MyThread ( ) {
}
public MyThread ( String name) {
super ( name) ;
}
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( getName ( ) + ": " + i) ;
}
}
}
public static void main ( String [ ] args) {
System . out. println ( Thread . currentThread ( ) . getName ( ) ) ;
}
1.5 线程调度
线程有两种调度模型: (1)分时调度模型:所有线程轮流使用CPU的使用权,平均分配每个线程占用CPU的时间片; (2)抢占式调度模型:优先让优先级高的线程使用CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取CPU时间片相对多一些; (3)Java使用的是抢占式调度模型。 多线程程序执行的随机性:假如只有一个CPU,那么CPU在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性 ,因为谁抢到CPU的使用权是不一定的。 Thread类中设置和获取线程优先级的方法: (1)public final int getPriority():返回此线程的优先级; (2)public final void setPriority(int newPriority):更改此线程的优先级。 (3)线程默认优先级是5 ,线程优先级范围是1~10 。线程优先级高仅仅表示线程获取CPU时间片的几率高,但是要在次数比较多,或者多次运行的时候才能看到你想要的效果。
public class MyThread extends Thread {
public MyThread ( ) {
}
public MyThread ( String name) {
super ( name) ;
}
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( getName ( ) + ": " + i) ;
}
}
}
public static void main ( String [ ] args) {
MyThread my1 = new MyThread ( "高铁" ) ;
MyThread my2 = new MyThread ( "飞机" ) ;
MyThread my3 = new MyThread ( "汽车" ) ;
System . out. println ( Thread . MAX_PRIORITY) ;
System . out. println ( Thread . MIN_PRIORITY) ;
System . out. println ( Thread . NORM_PRIORITY) ;
my1. setPriority ( 5 ) ;
my2. setPriority ( 7 ) ;
my3. setPriority ( 3 ) ;
my1. start ( ) ;
my2. start ( ) ;
my3. start ( ) ;
}
1.6 线程控制
方法名 说明 static void sleep(long millis) 使当前正在执行的线程停留(暂停执行)指定的毫秒数 void join() 等待这个线程死亡 void setDeamon(boolean on) 将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
public class ThreadSleep extends Thread {
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( getName ( ) + ": " + i) ;
try {
Thread . sleep ( 1000 ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
}
}
}
public static void main ( String [ ] args) {
ThreadSleep ts1 = new ThreadSleep ( ) ;
ThreadSleep ts2 = new ThreadSleep ( ) ;
ThreadSleep ts3 = new ThreadSleep ( ) ;
ts1. setName ( "曹操" ) ;
ts2. setName ( "刘备" ) ;
ts3. setName ( "孙权" ) ;
ts1. start ( ) ;
ts2. start ( ) ;
ts3. start ( ) ;
}
public class ThreadJoin extends Thread {
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( getName ( ) + ": " + i) ;
}
}
}
public static void main ( String [ ] args) {
ThreadJoin tj1 = new ThreadJoin ( ) ;
ThreadJoin tj2 = new ThreadJoin ( ) ;
ThreadJoin tj3 = new ThreadJoin ( ) ;
tj1. setName ( "康熙" ) ;
tj2. setName ( "四阿哥" ) ;
tj3. setName ( "八阿哥" ) ;
tj1. start ( ) ;
try {
tj1. join ( ) ;
} catch ( InterruptedException e) {
e. printStackTrace ( ) ;
}
tj2. start ( ) ;
tj3. start ( ) ;
}
public class ThreadDeamon extends Thread {
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( getName ( ) + ": " + i) ;
}
}
}
public static void main ( String [ ] args) {
ThreadDeamon td1 = new ThreadDeamon ( ) ;
ThreadDeamon td2 = new ThreadDeamon ( ) ;
td1. setName ( "关羽" ) ;
td2. setName ( "张飞" ) ;
Thread . currentThread ( ) . setName ( "刘备" ) ;
td1. setDaemon ( true ) ;
td2. setDaemon ( true ) ;
td1. start ( ) ;
td2. start ( ) ;
for ( int i = 0 ; i < 10 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + ":" + i) ;
}
}
1.7 线程生命周期
1.8 多线程的实现方式2
多线程的实现方案有两种: (1)继承Thread类; (2)实现Runable接口。 实现Runable接口: (1)定义一个类MyRunable实现Runable接口; (2)在MyRunable类中重写run(); (3)创建MyRunable类的对象; (4)创建Thread类的对象,把MyRunable对象作为构造方法的参数; (5)启动线程。 相比继承Thread类,实现Runable接口的好处: (1)避免了Java单继承的局限性; (2)适合多个相同程序的代码去处理同一个资源(在创建多个线程时我们把同一个MyRunable对象作为参数传递,这说明其为同一个资源)的情况,把线程和程序的代码、数据有效分离,较好地体现了面向对象的设计思想。
public class MyRunable implements Runnable {
@Override
public void run ( ) {
for ( int i = 0 ; i < 100 ; i++ ) {
System . out. println ( Thread . currentThread ( ) . getName ( ) + ": " + i) ;
}
}
}
public static void main ( String [ ] args) {
MyRunable mr = new MyRunable ( ) ;
Thread t1 = new Thread ( mr, "高铁" ) ;
Thread t2 = new Thread ( mr, "飞机" ) ;
t1. start ( ) ;
t2. start ( ) ;
}