多線程

1.如何解決多線程的安全問題?
校驗一個多線程程序是否有安全問題的隱患的前提條件:
1)當前程序是否是多線程環境
2)是否有共享數據
3)是否有多條語句對共享數據進行操作

  1. 鎖對象格式:
    synchronized(鎖對象){
    針對多條語句對共享數據操作代碼;
    }

    鎖對象:一定要同一個鎖(每個線程只能使用同一把鎖)
    
        售票問題
        package org.westos_05;

public class SellTicket implements Runnable {

//定義100張票
private int tickets = 100 ;

private Object obj = new Object() ;
private Demo d = new Demo() ;

@Override
public void run() {
    while(true) {

        //t1,t2,t3
        synchronized(d) { //門的開和關

            //t1進來,門會關掉
            //t2進來,門關掉
            //t3進來,門關掉
            if(tickets>0) {
                try {
                    //0.1
                    Thread.sleep(100); 
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
                System.out.println(Thread.currentThread().getName()
                        +"正在出售第"+(tickets--)+"張票");
                //窗口1正在出售第100張票
                //窗口2正在出售第99張票
                //窗口3正在出售98張票
                //....

                //雖然加入延遲操作,就是synchronized,不會存在0或者負票了
            }
        }

    }
}

}

public class SellTicketDemo {

public static void main(String[] args) {

    //創建資源類對象(共享資源類/目標對象)
    SellTicket st = new SellTicket() ;

    //創建線程類對象
    Thread t1 = new Thread(st, "窗口1") ;
    Thread t2 = new Thread(st ,"窗口2") ;
    Thread t3 = new Thread(st, "窗口3") ;

    //啓動線程

    t1.start();
    t2.start();
    t3.start();
}

}

還可以將鎖對象進行包裝,如果包裝成靜態類,鎖對象爲類名.class;
如果是非靜態類,鎖對象爲this ;

  1. //線程安全的類
    StringBuffer sb = new StringBuffer() ;
    Vector<String> v = new Vector<String>() ;
    Hashtable<String, String> hm = new Hashtable<String,String>() ;
    
    //Vector<String>它線程安全的類,還是不習慣使用這個集合,通過ArrayList集合:線程不安全的類
    List<String> array = new ArrayList(); //線程不安全的類
    
    //public static <T> List<T> synchronizedList(List<T> list)
    //返回指定列表支持的同步(線程安全的)列表
    List list = Collections.synchronizedList(array) ; //線程安全的方法
    1. // Jdk5.0以後,java提供了一個具體的鎖: 接口:Lock
      private Lock lock= new ReentrantLock(); //顯示獲取鎖的前提,一定要創建Lock接口對象

    Lock 實現提供了比使用 synchronized 方法和語句可獲得的更廣泛的鎖定操作。此實現允許更靈活的結構

    可以使用Lock鎖進行具體的鎖定操作類 提供了具體的實現類:ReentrantLock
    加鎖並且去釋放鎖

        package org.westos_07;

import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

public class SellTicket implements Runnable {

// 定義票
private int tickets = 100;
// Object obj = new Object();

// Jdk5.0以後,java提供了一個具體的鎖: 接口:Lock
private Lock lock= new ReentrantLock(); //顯示獲取鎖的前提,一定要創建Lock接口對象

@Override
public void run() {
    while (true) {
        try { //try...finally
            lock.lock(); // 獲取鎖    syncrhonized(obj)
            if (tickets > 0) {
                try {
                    Thread.sleep(100);
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }

                System.out.println(Thread.currentThread().getName() + "正在出售第" + (tickets--) + "張票");
            }

        } finally {//釋放鎖
            if(lock!=null) {
                lock.unlock();
            }

        }

    }

}

}

public class SellTicketDemo {

public static void main(String[] args) {

    SellTicket st = new SellTicket() ;

    Thread t1 = new Thread(st,"窗口1") ;
    Thread t2 = new Thread(st,"窗口2") ;
    Thread t3 = new Thread(st,"窗口3") ;
    //啓動線程
    t1.start(); 
    t2.start(); 
    t3.start();
}

}

5.消費者生產者問題解密死鎖;

package org.westos_11;

public class Student {

String name ;
int age ;

boolean flag; //默認沒有數據,如果是true,說明有數據

}

package org.westos_11;

//消費者線程
public class GetThread implements Runnable {
private Student s ;

    public GetThread(Student s) {
        this.s = s ;
    }

@Override
public void run() {
    //輸出該學生數據

// Student s = new Student() ;
while(true) {
synchronized (s) {
//如果本身消費者有數據
if(!s.flag) {
try {
s.wait();//和網絡編程中TCP編程裏面的accept() 都屬於阻塞式方法
//消費線程等待,等待該線程先輸出這些數據(立即釋放鎖對象)

                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            System.out.println(s.name +"----"+s.age);//高圓圓---27

            //如果沒有數據類,
            s.flag = false ;
            //通知t1線程,趕緊產生數據
            s.notify(); //喚醒單個線程
        }
        //張楊---27

    }

}

}

public SetThread(Student s) {
    this.s = s ;
}

//定義一個變量
private int x = 0 ;

@Override
public void run() {
    //設置學生數據

// Student s = new Student() ;
while(true) {
synchronized (s) {
//判斷有沒有數據的情況
if(s.flag) {

                try {
                    s.wait();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            if(x%2 ==0) {
                s.name = "高圓圓" ;    //高圓圓---27
                s.age = 27 ;
            }else {
                s.name = "張楊";
                //張楊
                s.age = 28 ;
            }
            x++ ;

            //如果有數據了,更改flag值
            s.flag = true ;//有數據了
            //通知t2線程消費數據,喚醒
            s.notify();  //喚醒t2線程,喚醒之後t1,t2都互相搶佔

        }

    }

}

}

public class StudentDemo {

public static void main(String[] args) {

    //針對同一個對象進行操作
    Student s = new Student() ;

    //創建線程類對象
    SetThread st = new SetThread(s) ;
    GetThread gt = new GetThread(s) ;

    //創建線程了對象
    Thread t1 = new Thread(st) ; //生產者
    Thread t2 = new Thread(gt) ;//消費者

    //啓動線程
    t1.start();
    t2.start();

}

}public class StudentDemo {

public static void main(String[] args) {

    //針對同一個對象進行操作
    Student s = new Student() ;

    //創建線程類對象
    SetThread st = new SetThread(s) ;
    GetThread gt = new GetThread(s) ;

    //創建線程了對象
    Thread t1 = new Thread(st) ; //生產者
    Thread t2 = new Thread(gt) ;//消費者

    //啓動線程
    t1.start();
    t2.start();

}

}

  1. 線程池問題

package org.westos_13;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

線程池:多個線程執行完畢,它會重新回到線程池中,等待被利用,不會變成垃圾!
和線程池有關的類
類 Executors: 一種工廠類

    方法:
        和線程池的創建有關係
        public static ExecutorService newFixedThreadPool(int nThreads)
        創建一個可重用固定線程數的線程池

ExecutorService:可以執行異步任務
創建一個線程池,執行接口中的方法
提交:Future<?> submit(Runnable task)
<T> Future<T> submit(Callable<T> task)提交一個返回值的任務用於執行,返回一個表示任務的未決結果的 Future
Future:接口
Future 表示異步計算的結果

        線程池調用完畢可以關閉的
            void shutdown():關閉之前,會提交剛纔的任務

public class ExceutorsDemo {

public static void main(String[] args) {

    //創建一個線程池
    ExecutorService pool = Executors.newFixedThreadPool(2) ;//創建一個線程池中包含了2條線程

    //提交和Runnable接口的方法或者Callable(提交任務)
    pool.submit( new MyRunnable()) ;
    pool.submit( new MyRunnable()) ;

    //pool-1-thread-2 :線程池-池數-線程類對象的描述-編號(從1開始)

    //關閉線程池
    pool.shutdown();

}

}

package org.westos_13;

public class MyRunnable implements Runnable {

@Override
public void run() {
    for(int x = 0 ; x < 100 ; x ++) {
        System.out.println(Thread.currentThread().getName()+":"+x);
    }

}

}

  1. 簡單工廠模式--->靜態工廠方法模式

    設計一個工廠類:
    工廠類提供一些靜態方法,間接的去創建具體的對象

    優點:
    不需要在創建具體類的對象,而是把創建的工作交給了工廠類來創建!
    弊端:如果有新的對象增加,或者某些對象的創建方式不同,就需要不斷的修改工廠類,不利於後期的維護

  2. 工廠方法模式
    提供一個抽象類(抽象工廠)還需要提供一個接口(工廠接口),每一個具體的類都有對應的工廠類(實現工廠接口)
    具體對象的創建工作由繼承抽象工廠的具體類實現

    優點:
    客戶端不需要在負責對象的創建(不需顯示創建具體對象),從而明確了各個類的職責,
    如果有新的對象增加,只需要增加一個具體的類和具體的工廠類即可,不影響已有的代碼,後期維護容易,增強 了系統的擴展性
    弊端:
    書寫代碼量大了!

  3. 設計模式之單例模式
    單例模式核心思想:某些類的對象在創建的時候 ,在系統內存始終只有一個對象!
    單例模式分類:
    1)餓漢式 2)懶漢式(類似於多線程環境..) 兩種分類在設計上幾乎一樣

  4. 餓漢式:
    在加載那個類的時候,對象的創建工作就已經完成了!

    1)定義個類,將該類的無參構造方法私有化
    2)在該類的成員位置創建該類對象 並且一定要私有化,防止外界更改這個對象
    3)在該類中提供靜態成員方法(返回值就是創建的那個對象),能被當前類直接調用,static修飾
  5. 懶漢式:
    符合單例模式核心思想
    1)自定義一個類,將無參構造私有化
    2)在成員位置聲明變量
    3)提供公共靜態功能,在裏面判斷的創建該類對象,返回該類對象

    如果是開發中,那麼就使用餓漢式(餓漢式它不會出現問題的單例模式)
    如果是面試中,那麼使用懶漢式(因爲他是可能出現問題的一種單例模式)

    1. 面試題:
      你使用過單例模式嗎?簡單介紹一種單例模式,請用代碼設計
      面試官想問的是:使用設計單例的懶漢式,能否想到使用同步機制解決線程的安全問題..

      懶漢式(延遲加載 -->懶加載)
      可能會出現問題
      ---> 多線程的問題
      --->校驗多線程安全問題的標準
      1)是否是多線程環境
      2)是否有共享數據
      3)是否有多條語句對共享數據進行操作 (使用同步機制進行操作)

13.網絡的概念
計算機網絡:
多臺計算機通過網絡協議,實現網絡資源共享和信息傳遞!

http://localhost:端口號 (80)www.baidu.com

username:admin
password:%AE%.... MD5算法 加密很難解密

網絡通信三要素

1)ip地址
2)端口號
3)應該有一些規則(協議UDP/TCP)

舉例:
    我想和高圓圓聊天...
    1)找到她,才能和她說話------>IP地址
    2)假設找她了,怎麼說呢?
        對着她耳朵說話------->port端口號
    3)要對她:i love you 
            假設不懂英文,----->定義規則(協議)

IP地址:
192.168.10.1 (通過8421碼將可以由0,1組成的一些數據)
點分十進制法:十進制.十進制.十進制.十進制 書寫簡單

    11000000.0000100....

    Ip地址的分類:

        IP地址的組成
        IP地址 = 網絡號碼+主機地址

        A類IP地址:第一段號碼爲網絡號碼,剩下的三段號碼爲本地計算機的號碼
                一般情況:國防部/大的國部門
        B類IP地址:前二段號碼爲網絡號碼,剩下的二段號碼爲本地計算機的號碼
                    一般情況:大學裏面的多媒體教室
        C類IP地址:前三段號碼爲網絡號碼,剩下的一段號碼爲本地計算機的號碼
                    私人地址

A類 1.0.0.1---127.255.255.254 (1)10.X.X.X是私有地址(私有地址就是在互聯網上不使用,而被用在局域網絡中的地址) (2)127.X.X.X是保留地址,用做循環測試用的。
B類 128.0.0.1---191.255.255.254 172.16.0.0---172.31.255.255是私有地址。169.254.X.X是保留地址。
C類 192.0.0.1---223.255.255.254 192.168.X.X是私有地址
D類 224.0.0.1---239.255.255.254
E類 240.0.0.1---247.255.255.254

127.0.0.1--->表示本地計算機的迴環地址
dos
ipconfig
ping ip地址 是否能通信

        聲吶系統(二戰)  

端口號:0~65535有效端口號
0-1024屬於保留端口

mysql:3306 

協議:
UDP協議 --->UDP編程
不需要建立連接通道的
數據大小有限制
不可靠連接
執行效率高
TCP協議 ---->TCP編程
需要建立連接通道
數據大小無限制
可靠連接
執行效率低

打電話:看成TCP協議  建立連接通道
發短信:UDP協議   不需要建立連接通道
  1. .InetAddress:類表示互聯網協議 (IP) 地址

    如果一個類中沒有構造方法,沒有字段,只有成員方法?有什麼特徵
    1)應該有一些靜態功能(Math類,Arrays,Collections...)
    2)可能符合一種單例模式(餓漢/懶漢)
    3)該類中的某些靜態成員方法的返回值是該類本身

    舉例
    public class Demo{

            public static Demo getDemo(){
                    new Demo() ;
            }
    }

    常用方法:
    public static InetAddress getByName(String host)
    throws UnknownHostException在給定主機名的情況下確定主機的 IP 地址。
    參數:
    主機名可以是機器名(如 "java.sun.com"),也可以是其 IP 地址的文本表示形式;

  2. Udp編程

    1)不需要建立連接通道
    2)數據大小有限制
    3)不可靠連接---->傳輸速度快!

    發送端的開發步驟:
    1)創建發送端的Socket對象
    2)創建數據,並打包
    3)調用當前發送端Socket對象中的發送的方法
    4)關閉資源

    方法: buf - 包數據。
    offset - 包數據偏移量。
    length - 包數據長度。
    address - 目的地址。
    port - 目的端口號。

    Udp編程的接收端 開發步驟:
    1)創建Socket對象
    2)創建一個數據報包(接收容器)
    3)調用Socket對象中的接收的方法
    4)解析實際傳遞的數據
    5)將解析的數據(ip,數據)展示在控制檯上
    6)關閉資源
    注意:
    接收端不要運行多次,會出現異常:
    java.net.BindException: Address already in use: Cannot bind

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章