多线程

  • 进程和线程的概述


Java 给多线程编程提供了内置的支持。 一条线程指的是进程中一个单一顺序的控制流,一个进程中可以并发多个线程,每条线程并行执行不同的任务。

多线程是多任务的一种特别的形式,但多线程使用了更小的资源开销。

这里定义和线程相关的另一个术语 - 进程:一个进程包括由操作系统分配的内存空间,包含一个或多个线程。一个线程不能独立的存在,它必须是进程的一部分。一个进程一直运行,直到所有的非守护线程都结束运行后才能结束。

多线程能满足程序员编写高效率的程序来达到充分利用 CPU 的目的。

线程生命周期,借用菜鸟教程的图一下

 

 

  • 线程实现


 

线程有两种实现方式,一种是继承Thread类实现,另外一种是实现Runnable接口实现,两种线程的实现方式,都是要实现run方法做为执行体的,以下分别记录两种线程实现方法的具体操作。

  • 继承Thread类实现

1.继承Thread类,并重写run方法

1 public class MyThread extends Thread{
2 
3     @Override
4     public void run() {
5     //执行体
6     }
7 }

  2.给MyThread类添加name属性和有参数构造方法,方便后面定义线程是命名(在这只是为了方便看)

 1 public class MyThread extends Thread{
 2 
 3     private String name;
 4     
 5     public MyThread(String name) {
 6         super();
 7         this.name = name;
 8     }
 9     
10     @Override
11     public void run() {
12 
13     }
14 }

  3.在线程体中添加要执行的代码部分,这里一输出一句内容为执行体作为实验,为了放慢速度来观察,让线程隔一秒休眠一次再运行

 1 @Override
 2     public void run() {
 3         
 4         System.out.println("我是线程"+name);
 5         
 6         try {
 7             Thread.sleep(1000);//休眠一秒
 8         } catch (InterruptedException e) {
 9             e.printStackTrace();
10         }
11     }

 

  4.创建一个测试类,添加主方法来实例化线程和运行

 1 public class TestMyThread {
 2 
 3     public static void main(String[] args) {
 4         
 5         MyThread thread1 = new MyThread("线程A");
 6         MyThread thread2 = new MyThread("线程B");
 7         
 8         thread1.start();//执行线程
 9         thread2.start();
10     }
11 }

 

  执行效果如下:

 

  • 实现Runnable接口,和上面一样,需要重写run方法,不同点在于实例化方式,实现Runnable接口的一个例子如下,通过在代码中注释,这里一步一步写了

 

  • 线程睡眠


sleep()是静态方法,所以最好的调用方法就是 Thread.sleep()。作用是让当前线程休眠,即当前线程会从“运行状态”进入到“休眠(阻塞)状态”。sleep()会指定休眠时间,线程休眠的时间会大于/等于该休眠时间;在线程重新被唤醒时,它会由“阻塞状态”变成“就绪状态”,从而等待cpu的调度执行。

 

sleep()与wait()的比较

wait()的作用是让当前线程由“运行状态”进入“等待(阻塞)状态”的同时,也会释放同步锁。而sleep()的作用是也是让当前线程由“运行状态”进入到“休眠(阻塞)状态”。但是,wait()会释放对象的同步锁,而sleep()则不会释放锁。

 

 

  • 线程同步synchronized


1.为了下面个同步的研究,首先创建一个Entry类,该类的作用是从0开始打印到9,表明线程的执行次数

 1 class Entry{
 2     
 3     public void show(String name) {//后面传入线程名
 4             
 5         for(int i = 0; i < 10; i++) {
 6                 
 7             try {
 8                     
 9                 Thread.sleep(1000);
10                 System.out.println(name+"----"+i);//线程名+执行序数i
11                     
12             } catch (InterruptedException e) {
13                     
14                 e.printStackTrace();
15             }
16         }
17             
18     }
19 }

 

2.创建线程执行体类

 1 public class MyThread extends Thread{
 2 
 3     private Entry entry;
 4     private String name;
 5     
 6     public MyThread(Entry entry, String name) {
 7         this.entry = entry;
 8         this.name = name;
 9     }
10 
11     @Override
12     public void run() {
13         
14         entry.show(name);
15     }
16 }

 

3.创建测试类

 1 public class Test {
 2 
 3     public static void main(String[] args) {
 4         Entry entry = new Entry();
 5         
 6         MyThread mt1 = new MyThread(entry, "线程1");
 7         MyThread mt2 = new MyThread(entry, "线程2");
 8         
 9         mt1.start();
10         mt2.start();
11     }
12 }

 

添加同步之前的执行效果:

看得出来,线程1和线程2是随机被执行的,这样不是我们想要的效果,那么需要同步。

 

4.所有的同步,在Entry类做修改,分别如下

同步实例方法

在该方法上加synchronized,如下

 1 class Entry{
 2     
 3     //线程同步成员方法,只对同一个对象调用次方法时有效,如果不是同一个对象,不行
 4     //线程同步成员方法
 5     public synchronized void show(String name) {
 6         
 7         for(int i = 0; i < 10; i++) {
 8             
 9             try {
10                 
11                 Thread.sleep(1000);
12                 System.out.println(name+"----"+i);
13                 
14             } catch (InterruptedException e) {
15                 
16                 e.printStackTrace();
17             }
18         }
19     }
20 }

 

同步后的执行效果如下

线程1一旦先获得资源执行,那么线程2只能等线程1执行完了才能开始。

 

同步类方法

将Entry类种的方法改为静态方法,并添加同步(在该方法上加synchronized),如下:

 1 class Entry{
 2     //类方法
 3     //线程同步类方法,无论使用同一个对象还时不同对象来调用次方法,同步都有效
 4     public synchronized static void show(String name) {
 5         
 6         for(int i = 0; i < 10; i++) {
 7             
 8             try {
 9                 
10                 Thread.sleep(1000);
11                 System.out.println(name+"----"+i);
12                 
13             } catch (InterruptedException e) {
14                 
15                 e.printStackTrace();
16             }
17         }
18     }
19 }

 

同步代码块

class Entry{

        public void show(String name) {
        
        //this,调用方法的对象
        synchronized (this) {//线程同步代码块
            
            for(int i = 0; i < 10; i++) {
                
                try {
                    
                    Thread.sleep(1000);
                    System.out.println(name+"----"+i);
                    
                } catch (InterruptedException e) {
                    
                    e.printStackTrace();
                }
            }
        }
            
    }
}

 

执行效果

 

posted @ 2018-08-07 23:53  四叶笔记  阅读(162)  评论(0编辑  收藏  举报