1. 程式人生 > >JUC(一、初識JUC)

JUC(一、初識JUC)

1、JUC是什麼?

2.首先要回憶一下什麼是程序和執行緒。

程序:程序是一個具有一定獨立功能的程式關於某個資料集合的一次執行活動。它是作業系統動態執行的基本單元,在傳統的作業系統中,程序既是基本的分配單元,也是基本的執行單元。
 
執行緒:通常在一個程序中可以包含若干個執行緒,當然一個程序中至少有一個執行緒,不然沒有存在的意義。執行緒可以利用程序所擁有的資源,在引入執行緒的作業系統中,通常都是把程序作為分配資源的基本單位,而把執行緒作為獨立執行和獨立排程的基本單位,由於執行緒比程序更小,基本上不擁有系統資源,故對它的排程所付出的開銷就會小得多,能更高效的提高系統多個程式間併發執行的程度。
 
舉例說明執行緒和程序

 
 使用QQ,檢視程序一定有一個QQ.exe的程序,我可以用qq和A文字聊天,和B視訊聊天,給C傳檔案,給D發一段語言,QQ支援錄入資訊的搜尋。
 
大四的時候寫論文,用word寫論文,同時用QQ音樂放音樂,同時用QQ聊天,多個程序。
 
word如沒有儲存,停電關機,再通電後開啟word可以恢復之前未儲存的文件,word也會檢查你的拼寫,兩個執行緒:容災備份,語法檢查
 
3.執行緒狀態

Thread.State
 
 
 
public enum State {
    /**
     * Thread state for a thread which has not yet started.
     */
    NEW,(新建)

    /**
     * Thread state for a runnable thread.  A thread in the runnable
     * state is executing in the Java virtual machine but it may
     * be waiting for other resources from the operating system
     * such as processor.
     */
    RUNNABLE,(準備就緒)

    /**
     * Thread state for a thread blocked waiting for a monitor lock.
     * A thread in the blocked state is waiting for a monitor lock
     * to enter a synchronized block/method or
     * reenter a synchronized block/method after calling
     * {@link Object#wait() Object.wait}.
     */
    BLOCKED,(阻塞)

    /**
     * Thread state for a waiting thread.
     * A thread is in the waiting state due to calling one of the
     * following methods:
     * <ul>
     *   <li>{@link Object#wait() Object.wait} with no timeout</li>
     *   <li>{@link #join() Thread.join} with no timeout</li>
     *   <li>{@link LockSupport#park() LockSupport.park}</li>
     * </ul>
     *
     * <p>A thread in the waiting state is waiting for another thread to
     * perform a particular action.
     *
     * For example, a thread that has called <tt>Object.wait()</tt>
     * on an object is waiting for another thread to call
     * <tt>Object.notify()</tt> or <tt>Object.notifyAll()</tt> on
     * that object. A thread that has called <tt>Thread.join()</tt>
     * is waiting for a specified thread to terminate.
     */
    WAITING,(不見不散)

    /**
     * Thread state for a waiting thread with a specified waiting time.
     * A thread is in the timed waiting state due to calling one of
     * the following methods with a specified positive waiting time:
     * <ul>
     *   <li>{@link #sleep Thread.sleep}</li>
     *   <li>{@link Object#wait(long) Object.wait} with timeout</li>
     *   <li>{@link #join(long) Thread.join} with timeout</li>
     *   <li>{@link LockSupport#parkNanos LockSupport.parkNanos}</li>
     *   <li>{@link LockSupport#parkUntil LockSupport.parkUntil}</li>
     * </ul>
     */
    TIMED_WAITING,(過時不候)

    /**
     * Thread state for a terminated thread.
     * The thread has completed execution.
     */
    TERMINATED;(終結)
}
 
 

4.wait/sleep的區別?

wait/sleep
功能都是當前執行緒暫停,有什麼區別?
wait放開手去睡,放開手裡的鎖,在哪裡睡就在哪裡醒
sleep握緊手去睡,醒了手裡還有鎖,在哪裡睡就在哪裡醒
 
 5.什麼是併發?什麼是並行?

併發:同一時刻多個執行緒在訪問同一個資源,多個執行緒對一個點
      例子:小米9今天上午10點,限量搶購
            春運搶票
            電商秒殺...
並行:多項工作一起執行,之後再彙總
      例子:泡方便麵,電水壺燒水,一邊撕調料倒入桶中

 6.接下來說一下Lock介面

 6.1是什麼

Lock implementations provide more extensive locking operations than can be obtained using synchronized methods and statements. They allow more flexible structuring, may have quite different properties, and may support multiple associated Condition objects. 
 
鎖實現提供了比使用同步方法和語句可以獲得的更廣泛的鎖操作。它們允許更靈活的結構,可能具有非常不同的屬性,並且可能支援多個關聯的條件物件。
 6.2 Lock介面的實現ReentrantLock可重入鎖

6.3如何使用呢

class X {
   private final ReentrantLock lock = new ReentrantLock();
   // ...
 
   public void m() {
     lock.lock();  // block until condition holds
     try {
       // ... method body
     } finally {
       lock.unlock()
     }
   }
 }

6.4建立執行緒的方式

6.4.1繼承Thread(java是單繼承,只能擴充套件一次資源寶貴,要用介面方式)

6.4.2new Thread()  Thread t1 = new Thread(); t1.start();也不能這麼寫

6.4.3

Thread(Runnable target, String name) 這個是什麼方式,研究一下

6.4.4實現runnable方法

class MyThread implements Runnable//新建類實現runnable介面
 
new Thread(new MyThread,...)
 
這種方法會新增類,有更新更好的方法

6.4.5 匿名內部類

new Thread(new Runnable() {
    @Override
    public void run() {
 
    }
   }, "your thread name").start();
 

 這種方法不需要建立新的類,可以new介面

6.4.6 lambda表示式(這個使用有前提,接口裡面只有一個未實現的方法(抽象方法)才可以,jdk1.8特性)

new Thread(() -> {
 
 }, "your thread name").start();
 

  這種方法程式碼更簡潔精煉

對於jdk1.8來說,在接口裡也是可以寫實現方法的,需要在方法前寫一個default關鍵字或者static關鍵字,就可以在接口裡寫具體的實現類了

程式碼如下:

package com.liuyuanyuan.thread;
 
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;
 
class Ticket //例項例eld +method
{
 private int number=30;
/* //1同步 public synchronized void sale() 
 {//2同步  synchronized(this) {}
  if(number > 0) {
    System.out.println(Thread.currentThread().getName()+"賣出"+(number--)+"\t 還剩number);
   }
 }*/
 
// Lock implementations provide more extensive locking operations
// than can be obtained using synchronized methods and statements. 
 private Lock lock = new ReentrantLock();//List list = new ArrayList()
 
 public void sale() 
 {
   lock.lock();
   
   try {
    if(number > 0) {
     System.out.println(Thread.currentThread().getName()+"賣出"+(number--)+"\t 還剩number);
    }
   } catch (Exception e) {
    e.printStackTrace();
   } finally {
    lock.unlock();
   }
   
 }
 
}
 
/**
 * 
 * @Description:賣票程式個售票出  0張票
 @author liuyuan
 * 筆記:J裡面如何 1 多執行緒編-上
    1.1 執行緒  (資裡源類 *   1.2 高內聚 /
public class SaleTicket 
{
 public static void main(String[] args)//main所有程式
   Ticket ticket = new Ticket();
   //Thread(Runnable target, String name) Allocates a new Thread object.
   
   
 new Thread(() -> {for (int i = 1; i < 40; i++)ticket.sale();}, "AA").start();
 new Thread(() -> {for (int i = 1; i < 40; i++)ticket.sale();}, "BB").start();
 new Thread(() -> {for (int i = 1; i < 40; i++)ticket.sale();}, "CC").start();

   
/*  new Thread(new Runnable() {
    @Override
    public void run() 
    {
     for (int i = 1; i <=40; i++) 
     {
       
       ticket.sale();
     }
    }
   }, "AA").start();
   
   new Thread(new Runnable() {
    @Override
    public void run() 
    {
     for (int i = 1; i <=40; i++) 
     {
       ticket.sale();
     }
    }
   }, "BB").start();
   new Thread(new Runnable() {
    @Override
    public void run() 
    {
     for (int i = 1; i <=40; i++) 
     {
       ticket.sale();
     }
    }
   }, "CC").start();
   */
 }
}
  
 
//1 class MyThread implements Runnable
 
//2 匿名內部類
 
//3 laExpress
 


1.5接下來介紹一下jdk1.8的特性lambda表示式

什麼是Lambda

Lambda 是一個匿名函式,我們可以把 Lambda
表示式理解為是一段可以傳遞的程式碼(將程式碼
像資料一樣進行傳遞)。可以寫出更簡潔、更
靈活的程式碼。作為一種更緊湊的程式碼風格,使
Java的語言表達能力得到了提升。
 
Lambda 表示式在Java 語言中引入了一個新的語法元
素和操作符。這個操作符為 “->” , 該操作符被稱
為 Lambda 操作符或剪頭操作符。它將 Lambda 分為
兩個部分:
左側:指定了 Lambda 表示式需要的所有引數
右側:指定了 Lambda 體,即 Lambda 表示式要執行
的功能


1.6  lambda表示式,如果一個介面只有一個方法,我可以把方法名省略
      Foo foo = () -> {System.out.println("****hello lambda");};
1.7 

lambda表示式,必須是函式式介面,必須只有一個方法
如果介面只有一個方法java預設它為函式式介面。
為了正確使用Lambda表示式,需要給介面加個註解:@FunctionalInterface
如有兩個方法,立刻報錯
 
Runnable介面為什麼可以用lambda表示式?

 

接口裡是否能有實現方法?

default方法
接口裡在java8後容許有介面的實現,default方法預設實現
default int div(int x,int y) {
  return x/y;
 }
接口裡default方法可以有幾個?
 

靜態方法實現
 靜態方法實現:介面新增 
public static int sub(int x,int y){
  return x-y;
}
可以有幾個?
注意靜態的叫類方法,能用foo去調嗎?要改成Foo
程式碼實現:

package com.liuyuanyuan.thread;
@FunctionalInterface
interface Foo{
 
// public void sayHello() ;
// public void say886() ;
 
 public int add(int x,int y);
 
 default int div(int x,int y) {
   return x/y;
 }
 
 public static int sub(int x,int y) {
   return x-y;
 }
}
 
 
 
/**
 * 
 * @Description: Lambda Express-----> 函數語言程式設計
 * @author xialei
 * 1 拷貝小括號(形參列表),寫死右箭頭 ->,落地大括號 {方法實現}
 * 2 有且只有一個public方法@FunctionalInterface註解增強定義
 * 3 default方法預設實現
 * 4 靜態方法實現
 */
public class LambdaDemo
{
 public static void main(String[] args)
 {
//  Foo foo = new Foo() {
//   @Override
//   public void sayHello() {
//     System.out.println("Hello!!");
//   }
//
//   @Override
//   public void say886() {
//     // TODO Auto-generated method stub
//     
//   }
//  };
//  foo.sayHello();
//  System.out.println("============");
//  foo = ()->{System.out.println("Hello!! lambda !!");};
//  foo.sayHello();
 
 Foo foo = (x,y)->{
   System.out.println("Hello!! lambda !!");
   return x+y;
   };
   
   int result = foo.add(3,5);
   System.out.println("******result="+result);
   System.out.println("******result div="+foo.div(10, 2));
   System.out.println("******result sub="+Foo.sub(10, 2));