Java之多线程


2018/12/24 Java

多线程即在同一时间,可以做多件事情。

因为CPU的速度是非常非常快的,所以可以在同一时间做很多事情,实际上CPU是在同一时间只能做一件事情,因为处理的速度实在是太快,所以可以接近同一时间做很多事情,像我的CPUi5-8500六核六线程,CPU自带的有6个线程,有些高端CPU还有超线程功能(可以虚拟出额外的线程)

# 创建一个线程

创建多线程有3种方式,分别是继承线程类,实现Runnable接口,匿名类
线程概念
首先要理解进程(Processor)和线程(Thread)的区别 进程:启动一个LOL.exe就叫一个进程。 接着又启动一个DOTA.exe,这叫两个进程。 线程:线程是在进程内部同时做的事情.

# 继承线程类

设计一个类XxxxThread 继承Thread,并且重写run方法 启动线程办法: 实例化一个XxxxThread对象,并且调用其start方法

public class XxxxThread extends Thread{
     
    public void run(){
        //这里面写一些要运行的东西
        xxx...
    }
}
1
2
3
4
5
6
7

其他地方如果要运行这个线程Thread,可以用start()方法调用

public class TestThread {
 
    public static void main(String[] args) {
         //可以启动多个线程    
        XxxxThread XxxxThread1 = new XxxxThread();
        XxxxThread1.start();
        XxxxThread XxxxThread2 = new XxxxThread();
        XxxxThread.start();
         
    }
     
}
1
2
3
4
5
6
7
8
9
10
11
12

# 实现Runnable接口

创建类Battle,实现Runnable接口 启动的时候,首先创建一个Battle对象,然后再根据该battle对象创建一个线程对象,并启动

Battle Battle1 = new Battle();
new Thread(Battle1).start();
1
2

battle1 对象实现了Runnable接口,所以有run方法,但是直接调用run方法,并不会启动一个新的线程。
必须,借助一个线程对象的start()方法,才会启动一个新的线程。
所以,在创建Thread对象的时候,把battle1作为构造方法的参数传递进去,这个线程启动的时候,就会去执行battle1.run()方法了。

public class Battle implements Runnable{
    public void run(){
        Xxxx...
    }
}
1
2
3
4
5
package multiplethread;
 
public class TestThread {
 
    public static void main(String[] args) {
        //新建线程对象
        Battle battle1 = new Battle();
        //启动线程
        new Thread(battle1).start();
 
        Battle battle2 = new Battle(bh,leesin);
        new Thread(battle2).start();
 
    }
     
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16

# 匿名类

使用匿名类,继承Thread,重写run方法,直接在run方法中写业务代码 匿名类的一个好处是可以很方便的访问外部的局部变量。 前提是外部的局部变量需要被声明为final。(JDK7以后就不需要了).

class Hero{
    public String name;
    public int HP;
    public int lavel;
}
public class TestThread{
    public static void main(String[] args) {
        
        Hero gareen = new Hero();
        gareen.name="盖伦";
        gareen.HP=600;

        //匿名类
        Thread t1= new Thread(){
            public void run(){
                //匿名类中用到外部的局部变量,必须把外部的局部变量声明为final
                //但是在JDK7以后,就不是必须加final的了
                System.out.println("Hello World!"+gareen.name);
            }
        };
        t1.start();
        Thread t2= new Thread(){
            public void run(){
                System.out.println("Hello World!"+gareen.HP);
            }
        };
        t2.start();
    }
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29

注: 启动线程是start()方法,run()并不能启动一个新的线程

# 常见线程方法

# 暂停当前线程

关键词:sleep()
Thread.sleep(1000); 表示当前线程暂停1000毫秒 ,其他线程不受影响 Thread.sleep(1000); 会抛出InterruptedException 中断异常,因为当前线程sleep的时候,有可能被停止,这时就会抛出 InterruptedException

package multiplethread;   //multiple adj.多样的,多重的  
 
public class TestThread {
 
    public static void main(String[] args) {
         
        Thread t1= new Thread(){
            public void run(){
                int seconds =0;
                while(true){
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.printf("已经玩了LOL %d 秒%n", seconds++);
                }              
            }
        };
        t1.start();
         
    }
     
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25

# 加入到当前线程中

关键词:join() 首先解释一下主线程的概念 所有进程,至少会有一个线程即主线程,即main方法开始执行,就会有一个看不见的主线程存在。 在42行执行t.join,即表明在主线程中加入该线程。 主线程会等待该线程结束完毕, 才会往下运行。

class Hero{
    public String name;
    public int HP;
    public int lavel;
}

public class TestThread {
    
    public static void main(String[] args) {

        Hero gareen = new Hero();
        gareen.name="盖伦";
        gareen.HP=600;
                    
        Thread t1= new Thread(){
            public void run(){
                System.out.println("Hello"+gareen.name);              
            }
        };
            
        t1.start();
    
        //代码执行到这里,一直是main线程在运行
        try {
            //t1线程加入到main线程中来,只有t1线程运行结束,才会继续往下走
            t1.join();
        } catch (InterruptedException e) {
            e.printStackTrace();
        }
            
    }
        
}
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33

Initializing...

山楂树之恋
程佳佳