1. 程式人生 > >實驗十六 執行緒技術

實驗十六 執行緒技術

                                                                                實驗十六  執行緒技術

                                                                                                  實驗時間 2017-12-8

1、實驗目的與要求

(1) 掌握執行緒概念;

(2) 掌握執行緒建立的兩種技術;

(3) 理解和掌握執行緒的優先順序屬性及排程方法;

(4) 掌握執行緒同步的概念及實現技術;

2、實驗內容和步驟

實驗1:測試程式並進行程式碼註釋。

測試程式1:

l 在elipse IDE中除錯執行ThreadTest,結合程式執行結果理解程式;

l 掌握執行緒概念;

l 掌握用Thread的擴充套件類實現執行緒的方法;

l 利用Runnable介面改造程式,掌握用Runnable介面建立執行緒的方法。

class Lefthand extends Thread { 

   public void run()

   {

       for(int i=0;i<=5;i++)

       {  System.out.println("You are Students!");

           try{   sleep(500);   }

           catch(InterruptedException e)

           { System.out.println("Lefthand error.");}    

       } 

  } 

}

class Righthand extends Thread {

    public void run()

    {

         for(int i=0;i<=5;i++)

         {   System.out.println("I am a Teacher!");

             try{  sleep(300);  }

             catch(InterruptedException e)

             { System.out.println("Righthand error.");}

         }

    }

}

public class ThreadTest 

{

     static Lefthand left;

     static Righthand right;

     public static void main(String[] args)

     {     left=new Lefthand();

           right=new Righthand();

           left.start();

           right.start();

     }

}

 測試結果:

利用Runnable介面改造程式,掌握用Runnable介面建立執行緒的方法。原始碼如下

package Demo1;

class Lefthand implements Runnable {
    public void run() {
        for (int i = 0; i <= 5; i++) {
            System.out.println("You are Students!");
            try {
                Thread.sleep(500);
            } catch (InterruptedException e) {
                System.out.println("Lefthand error.");
            }
        }
    }
}

class Righthand implements Runnable {
    public void run() {
        for (int i = 0; i <= 5; i++) {
            System.out.println("I am a Teacher!");
            try {
                Thread.sleep(300);
            } catch (InterruptedException e) {
                System.out.println("Righthand error.");
            }
        }
    }
}

public class ThreadTest {
    static Lefthand left;
    static Righthand right;

    public static void main(String[] args) {
        Runnable left1 = new Lefthand();
        Runnable right1 = new Righthand() ;
        Thread left = new Thread(left1);
        Thread right = new Thread(right1);
        left.start();
        right.start();
    }
}

 

測試程式2

l 在Elipse環境下除錯教材625頁程式14-1、14-2 14-3,結合程式執行結果理解程式;

l 在Elipse環境下除錯教材631頁程式14-4,結合程式執行結果理解程式;

l 對比兩個程式,理解執行緒的概念和用途;

l 掌握執行緒建立的兩種技術。

程式執行結果:

執行程式14-4

 

 

測試程式3:分析以下程式執行結果並理解程式。

class Race extends Thread {

  public static void main(String args[]) {

    Race[] runner=new Race[4];

    for(int i=0;i<4;i++) runner[i]=new Race( );

   for(int i=0;i<4;i++) runner[i].start( );

   runner[1].setPriority(MIN_PRIORITY);

   runner[3].setPriority(MAX_PRIORITY);}

  public void run( ) {

      for(int i=0; i<1000000; i++);

      System.out.println(getName()+"執行緒的優先順序是"+getPriority()+"已計算完畢!");

    }

}

 

測試程式4

l 教材642頁程式模擬一個有若干賬戶的銀行,隨機地生成在這些賬戶之間轉移錢款的交易。每一個賬戶有一個執行緒。在每一筆交易中,會從執行緒所服務的賬戶中隨機轉移一定數目的錢款到另一個隨機賬戶。

l 在Elipse環境下除錯教材642頁程式14-5、14-6,結合程式執行結果理解程式;

 

綜合程式設計練習

程式設計練習1

  1. 設計一個使用者資訊採集程式,要求如下:

(1) 使用者資訊輸入介面如下圖所示:

 

 

(2) 使用者點選提交按鈕時,使用者輸入資訊顯示控制檯介面;

(3) 使用者點選重置按鈕後,清空使用者已輸入資訊;

(4) 點選視窗關閉,程式退出。

2.建立兩個執行緒,每個執行緒按順序輸出5次“你好”,每個“你好”要標明來自哪個執行緒及其順序號。

3. 完善實驗十五 GUI綜合程式設計練習程式。

1.實驗原始碼:

Main:

 

import java.awt.EventQueue;

import javax.swing.JFrame;

public class Mian {
    public static void main(String[] args) {
        EventQueue.invokeLater(() -> {
            demo page = new demo();
        });
    }
}

 

WinCenter:

import java.awt.Dimension;
import java.awt.Toolkit;
import java.awt.Window;

public class WinCenter {
    public static void center(Window win){
        Toolkit tkit = Toolkit.getDefaultToolkit();
        Dimension sSize = tkit.getScreenSize();
        Dimension wSize = win.getSize();
        if(wSize.height > sSize.height){
            wSize.height = sSize.height;
        }
        if(wSize.width > sSize.width) {
            wSize.width = sSize.width;
        }
        win.setLocation((sSize.width - wSize.width)/ 2, (sSize.height - wSize.height)/ 2);
    }
}

demo:

import java.awt.*;
import java.awt.event.*;
import javax.swing.*;
import javax.swing.border.*;
public class demo extends JFrame {
    public demo() {
        JPanel panel1 = new JPanel();
        panel1.setPreferredSize(new Dimension(700, 45));
        panel1.setLayout(new GridLayout(1, 4));
        JLabel label1 = new JLabel("Name:");
        JTextField j1 = new JTextField("");
        JLabel label2 = new JLabel("Qualification:");
        JComboBox<Object> j2 = new JComboBox<>();
        j2.addItem("Graduate");
        j2.addItem("Not Graduate");
        panel1.add(label1);
        panel1.add(j1);
        panel1.add(label2);
        panel1.add(j2);

        JPanel panel2 = new JPanel();
        panel2.setPreferredSize(new Dimension(700, 50));
        panel2.setLayout(new GridLayout(1, 4));
        JLabel label3 = new JLabel("Address:");
        JTextArea j3 = new JTextArea();
        JLabel label4 = new JLabel("Hobby:");
        JPanel p = new JPanel();
        p.setLayout(new GridLayout(3, 1));
        p.setBorder(BorderFactory.createLineBorder(null));
        JCheckBox c1 = new JCheckBox("Reading");
        JCheckBox c2 = new JCheckBox("Singing");
        JCheckBox c3 = new JCheckBox("Dancing");
        p.add(c1);
        p.add(c2);
        p.add(c3);
        panel2.add(label3);
        panel2.add(j3);
        panel2.add(label4);
        panel2.add(p);

        JPanel panel3 = new JPanel();
        panel3.setPreferredSize(new Dimension(700, 150));
        FlowLayout flowLayout1 = new FlowLayout(FlowLayout.LEFT, 20, 40);
        panel3.setLayout(flowLayout1);
        JLabel label5 = new JLabel("Sex:");
        JPanel p1 = new JPanel();
        p1.setLayout(new GridLayout(2,1));
        p1.setBorder(BorderFactory.createLineBorder(null));
        ButtonGroup bu = new ButtonGroup();
        JRadioButton jr1 = new JRadioButton("Male");
        JRadioButton jr2 = new JRadioButton("Female");
        bu.add(jr1);
        bu.add(jr2);
        p1.add(jr1);
        p1.add(jr2);
        panel3.add(label5);
        panel3.add(p1);
        add(panel1);
        add(panel2);
        add(panel3);

        JPanel panel4 = new JPanel();
        panel4.setPreferredSize(new Dimension(700, 150));
        JButton b1 = new JButton("Validate");
        panel4.add(b1);
        JButton b2 = new JButton("Reset");
        panel4.add(b2);
        add(panel4);

        FlowLayout flowLayout = new FlowLayout();
        this.setLayout(flowLayout);
        this.setTitle("Students Detail");
        this.setBounds(200, 200, 800, 400);
        this.setVisible(true);
        this.setDefaultCloseOperation(DISPOSE_ON_CLOSE);

        b1.addActionListener(new ActionListener() {

        
            public void actionPerformed(ActionEvent e) {
                // TODO 自動生成的方法存根
                String xueli = j2.getSelectedItem().toString();
                System.out.println("Name:" + j1.getText());
                System.out.println("Qualification:" + xueli);
                String hobbystring = "Hobby:";
                if (c1.isSelected()) {
                    hobbystring += "Reading";
                }
                if (c2.isSelected()) {
                    hobbystring += "Singing";
                }
                if (c3.isSelected()) {
                    hobbystring += "Dancing";
                }
                System.out.println("Address:" + j3.getText());
                if (jr1.isSelected()) {
                    System.out.println("Sex:Male");
                }
                if (jr2.isSelected()) {
                    System.out.println("Sex:Female");
                }
                System.out.println(hobbystring);
            }
        });
        b2.addActionListener(new ActionListener() {

            public void actionPerformed(ActionEvent e) {
                // TODO 自動生成的方法存根
                j1.setText(null);
                j3.setText(null);
                j2.setSelectedIndex(0);
                c1.setSelected(false);
                c2.setSelected(false);
                c3.setSelected(false);
                bu.clearSelection();
            }
        });
    }

    public static void main(String args[]) {
        new demo();
    }

}

實驗執行結果:

 

 

2.實驗原始碼

class Lefthand extends Thread {
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(i+":1.你好!");
            try {
                sleep(300);
            } catch (InterruptedException e) {
                System.out.println("Lefthand error.");
            }
        }
    }
}

class Righthand extends Thread {
    public void run() {
        for (int i = 1; i <= 5; i++) {
            System.out.println(i+":2.你好!");
            try {
                sleep(300);
            } catch (InterruptedException e) {
                System.out.println("Righthand error.");
            }
        }
    }
}

public class ThreadTest {
    static Lefthand left;
    static Righthand right;

    public static void main(String[] args) {
        left = new Lefthand();
        right = new Righthand();
        left.start();
        right.start();
    }
}

實驗執行結果:

 實驗總結:

        執行緒與程序的概念:

程式是一段靜態的程式碼,它是應用程式執行的藍本。

‐程序是程式的一次動態執行,它對應了從程式碼載入、執行至執行完畢的一個完整過程。

‐作業系統為每個程序分配一段獨立的記憶體空間和系統資源,包括:程式碼資料以及堆疊等資源。每一個程序的內部資料和狀態都是完全獨立的。

‐多工作業系統中,程序切換對CPU資源消耗較大

多執行緒的概念:

多執行緒是程序執行過程中產生的多條執行線索。

‐執行緒是比程序執行更小的單位。

‐執行緒不能獨立存在,必須存在於程序中,同一程序的各執行緒間共享程序空間的資料。

‐每個執行緒有它自身的產生、存在和消亡的過程,是一個動態的概念。

‐多執行緒意味著一個程式的多行語句可以看上去幾乎在同一時間內同時執行。

‐執行緒建立、銷燬和切換的負荷遠小於程序,又稱為輕量級程序(lightweight process)。

中斷執行緒:

 當執行緒的run方法執行方法體中最後一條語句後,或者出現了在run方法中沒有捕獲的異常時,執行緒將終止,讓出CPU使用權。

 呼叫interrupt()方法也可終止執行緒。void interrupt()

– 向一個執行緒傳送一箇中斷請求,同時把這個線程的“interrupted”狀態置為true。

– 若該執行緒處於 blocked 狀 態 , 會丟擲InterruptedException。 

執行緒阻塞的三種情況:

 等待阻塞 -- 通過呼叫執行緒的wait()方法,讓線程等待某工作的完成。

 同步阻塞 -- 執行緒在獲取synchronized同步鎖失敗(因為鎖被其它執行緒所佔用),它會進入同步阻塞狀態。

 其他阻塞 -- 通過呼叫執行緒的sleep()或join()或發出了I/O請求時,執行緒會進入到阻塞狀態。當sleep()狀態超時、join()等待執行緒終止或者超時、或者I/O處理完畢時,執行緒重新轉入就緒狀態

執行緒的狀態:

多執行緒排程:

Java提供一個執行緒排程器來監控程式啟動後進入可執行狀態的所有執行緒。執行緒排程器按照執行緒的優先順序決定應排程哪些執行緒來執行。

– 處於可執行狀態的執行緒首先進入就緒佇列排隊等候處理器資源,同一時刻在就緒佇列中的執行緒可候多個。Java的多執行緒系統會給每個執行緒自動分配一個執行緒的優先順序。

守護執行緒:

 守護執行緒的惟一用途是為其他執行緒提供服務。例如計時執行緒。

 若JVM的執行任務只剩下守護執行緒時,JVM就退出了。

 在一個執行緒啟動之前,呼叫setDaemon方法可將執行緒轉換為守護執行緒(daemon thread)。

實驗總結:        通過本週理論知識的學習以及在實驗課上所做的實驗,我掌握了執行緒的概念,並且在實際的程式設計環境下也懂得了如何去理論執行緒的知識點在頁面佈局管理器上編輯一些東西,但是在縣城的中斷這一方面掌握的還不是太好。