多线程

多线程  概述

1.进程:是一个正在执行中的程序。

每个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元(线程)。

2.线程:就是进程中的一个独立的控制单元。

线程控制着进程的执行,一个进程中,至少有一个或一个以上的线程。

创建线程的第一种方式:继承Thread类。

步骤:

1.定义类继承Thread。

2.复写Thread类中的run方法(目的:将自定义代码存储在run方法。让线程运行)

3.调用线程的Start方法,该方法两个作用:启动线程,调用run方法(直接调用run方法也是可以的,但是那样就不是多线程了)

 1 class ThreadTest extends Thread{ 
 2 
 3 
 4 
 5         public void run(){ 
 6 
 7 
 8 
 9         线程运行代码; 
10 
11         } 
12 } 
13 
14 class Test{ 
15 
16         public static void main(String[] args){ 
17 
18 
19         ThreadTest threadTest = new ThreadTest(); 
20 
21         thread.start(); 
22 
23         } 
24 
25 } 
26 
27 
28 
29                     

也可以使用匿名内部类的方式:

 1 class Test{ 
 2 
 3         public static void main(String[] args){ 
 4 
 5                 new Thread(){ 
 6 
 7                     public void run(){ 
 8 
 9                     线程运行代码; 
10 
11                     } 
12 
13                 }.start(); 
14 
15         } 
16 
17 } 

创建线程的第二种方式:实现Runnable接口

实现步骤:

1.定义类实现Runnable接口
2.覆盖Runnable接口中的run方法,将线程要运行的代码存放在该run方法中。

3.通过Thread建立线程对象

4.Runnable接口的子类对象作为实际参数传递给Thread的构造函数。

5.调用Thread类的start方法开启线程并调用Runnable接口子类的的run方法。

 1 class RunnableTest implements Runnable{ 
 2 
 3         public void run(){ 
 4 
 5 
 6         线程要运行代码; 
 7 
 8         } 
 9 
10 }
11 
12 class TestDemo{ 
13 
14         public static void main(String[] args){ 
15 
16             RunnableTest runnableTest = new RunnableTest();
17             Thread thread = new Thread(runnableTest);
18             thread.start();
19         /*
20         简化到一步  new Thread(new Runnable()).start();
21 
22         */ 
23 
24         } 
25 
26 
27 } 

使用匿名内部类:

 1 class TestDemo{ 
 2 
 3         public static void main(String[] args){ 
 4 
 5                 new Thread(new Runnable(){ 
 6     
 7                         public void run(){ 
 8 
 9                             线程要运行代码; 
10 
11                         } 
12                 }).start(); 
13 
14         } 
15 
16 } 

为什么要将Runnable接口的子类对象传递给Thread的构造函数。

因为,自定义的run方法所属的对象是Runnable接口的子接口对象。 所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。

实现方式和继承方式有什么区别:

(1)、实现方式好处:避免了单继承的局限性。

(2)、在定义线程时:建议使用实现方式

 

(3)、两种方式区别:

1.继承Thread:线程代码存放在 Thread 子类 run 方法中(单继承)

2.实现Runnable:线程代码存放在接口的子类的 run 方法中(建议使用这种方式,可以实现多继承接口)

 

多线程好处:

原本我们如果是单线程的情况下,我们定义在死循环就一直运行死循环的代码,不会运行其他的代码。 多线程的好处就体现出来了,他可以让我们的代码实现同步运行。

发现运行结果每一次都不同

因为多个线程都获取CPU的执行权。CPU执行到谁,谁就运行。

明确一点,在某一个时刻,只能有一个序在运行。(多核除外)。

CPU在做着快速的切换,以达到看上去是同时运行的效果。

线程(Thread)类中已经封装好的方法:

static Thread currentThread():获取当前线程对象。

getName(): 获取线程名称。 设置线程名称:setName或者构造函数。(线程都有自己默认的名字,Thread-编号 该编号从0开始。

注意:主线程不会设置名称,它的线程名是默认的(main);

 

线程间的通讯通信

 

线程间通信-等待唤醒机制

wait(),notify(),notifyAll(),都使用在同步中,因为要对持有监视器(锁)的线程操作。

这些方法在操作同步中,线程同步,都必须要表示它们所操作线程持有的锁,只有同一个锁上的被等待线程,可以被同一个锁notify唤醒,不可以对不同锁中的线程进行等待唤醒。 也就是说,等待和唤醒必须是同一个锁。所以要使用在同步中,因为只有同步才具有锁。

wait()   sleep()的区别

 

wait()   :释放资源,释放锁 。

sleep()   :释放资源,不释放锁。

其实就是多个线程在操作同一个但是操作的动作不同(一个是wait 一个是notify)。

同步:

对象如同锁,持有锁的线程可以在同步中执行,没有持有锁的线程即使获取CPU的执行权,也进不去,因为没有获取锁。

好处:解决了多线程的安全问题

弊端:多个线程需要判断锁,较为消耗资源。

package com.lovo;
/**
 * 同步代码块
 * @author Mine
 *
 */
public  class Sync implements Runnable{
        private int value;
        
        public void run(){
            for(int count=0;count<3;count++){
                synchronized(this){//当使用对象锁时,其他线程是无法使用这个块的代码 ,所以value的值是连续的
                    value++;
                    try {
                        Thread.sleep(1000);//线程休眠
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                }
                System.out.println(Thread.currentThread().getName()+":value="+value);//打印value的值
                
            }
        }
}


package com.lovo;

public class SyncTest {
        public static void main(String[] args){
            Sync s=new Sync();
            new Thread(s).start();
            new Thread(s).start();
        }
}
package com.lovo;
/**
 * 同步方法
 * @author Mine
 *
 */
public class Syncc implements Runnable {
        private int value;
        
        public void run(){
            printValue();
        }
        
       public synchronized void printValue(){
            for(int count=0;count<3;count++){
                value++;
                try {
                    Thread.sleep(1000);
                } catch (InterruptedException e) {
                    
                }
                System.out.println(Thread.currentThread().getName()+"value="+value);
            }
            
        }
}


package com.lovo;

public class SynccTest {
        public static void main(String[] args){
            Syncc s=new Syncc();
            new Thread(s).start();
            new Thread(s).start();
        }
}
原文地址:https://www.cnblogs.com/Melony/p/4471542.html