java多線程--幾個多線程面試題小結


  自學了一段時間的多線程知識,嘗試了做了幾個編程題,發現想象中很簡單的功能,自己真寫起來要花費遠超自己想象的功夫,知識點易學,不易用啊.

面試題1:編寫程序實現,子線程循環10次,接着主線程循環20次,接着再子線程循環10次,主線程循環20次,如此反復,循環50次.

package com.wang.reflect; //編寫功能類,實現子線程和主線程的功能
class Function{ private boolean flag=false; //子線程要實現的功能
    public synchronized void sub(){ while(flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for(int i=0;i<10;i++){ //for循環內定義子線程的功能,這里簡單的假設為打印一句話,主線程同理
            System.out.println("sub"+i); } flag=true; this.notify(); } //主線程要實現的功能
    public synchronized void main(){ while(!flag){ try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } for(int i=0;i<20;i++){ System.out.println("main"+i); } flag=false; this.notify(); } } public class Demo01 { public static void main(String[] args) { final Function f=new Function(); new Thread( new Runnable(){ @Override public void run() { for(int i=0;i<50;i++){ f.sub(); } } } ).start(); for(int i=0;i<50;i++){ f.main(); } } }

  JDK1.5以后,出現了Lock和condition,Lock類似於synchronized功能,用來進行線程同步,Condition功能類似於Object類中的wait和notify方法,用於線程間的通信.上面的代碼可以用Lock和Condition來改進,如下:

 

package com.wang.reflect;

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

//編寫功能類,實現子線程和主線程的功能
class Function{
    private boolean flag=false;
    
    Lock lock=new ReentrantLock();
    Condition con=lock.newCondition();
    //子線程要實現的功能
    public  void sub(){
        lock.lock();
        try {
            
            while(flag){
                try {
                    con.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            
            
            for(int i=0;i<10;i++){
                //for循環內定義子線程的功能,這里簡單的假設為打印一句話,主線程同理
                System.out.println("sub"+i);
            }
            
            flag=true;
            con.signal();
        } finally{
            lock.unlock();
        }
    }
    //主線程要實現的功能
    public synchronized void main(){
        lock.lock();
        try {
            while (!flag) {
                try {
                    con.await();
                } catch (InterruptedException e) {
                    e.printStackTrace();
                }
            }
            for (int i = 0; i < 20; i++) {
                System.out.println("main" + i);
            }
            flag = false;
            con.signal();
        } finally{
            lock.unlock();
        }
    }
    
}


public class Demo01 {

    
    
    public static void main(String[] args) {
         final Function f=new Function();
        new Thread(
                new Runnable(){

                    @Override
                    public void run() {
                        for(int i=0;i<50;i++){
                            f.sub();
                        }
                    }
                
                }
                ).start();
        
        for(int i=0;i<50;i++){
            f.main();
        }
    }
}

 

 

 

面試題2:設計四個線程,其中兩個線程每次對變量i加1,另外兩個線程每次對i減1.

package com.wang.reflect; /** * 設計四個線程,其中兩個線程每次對變量i加1,另外兩個線程每次對i減1. * @author Administrator * */
public class Demo02 { private int  i=0; public static void main(String[] args) { Demo02 demo=new Demo02(); Add add = demo.new Add(); Sub sub = demo.new Sub(); for(int i=1;i<=2;i++){ new Thread(add,"線程"+i).start(); new Thread(sub,"線程"+i).start(); } } //定義一個內部類Add,實現功能每次對i加一
    class Add implements Runnable{ @Override public void run() { for(int i=0;i<10;i++){ addOne(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } //定義一個內部類Sub,實現功能每次對i減1
    class Sub implements Runnable{ @Override public void run() { for(int i=0;i<10;i++){ subOne(); try { Thread.sleep(100); } catch (InterruptedException e) { e.printStackTrace(); } } } } public synchronized void addOne() { i++; System.out.println(Thread.currentThread().getName()+"加一的值為:"+i); } public synchronized void subOne(){ i--; System.out.println(Thread.currentThread().getName()+"減一的值為:"+i); } }

面試題3:自己編寫代碼,實現生產者-消費者模型功能.內容自由發揮,只需要表達思想.

  代碼中,自定義一個學生類,有name和age屬性,屬於共享對象,生產者負責為studnet對象賦值,消費者負責打印出student對象的name和age的值,當生產者賦值完以后通知消費者來打印,消費者打印完以后,通知生產者重新設置.

package com.wang.reflect; //學生實體類作為共享資源
class Student { private String name;// 姓名
    private int age;// 年齡
    boolean flag;// 標記變量,判斷當前學生對象是否已創建賦值好 //生產者的功能 ,為studnet對象賦值
    public synchronized void set(String name, int age) { if (this.flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } this.name = name; this.age = age; this.flag = true; this.notify(); } //消費者的功能,打印sutdent對象的內容
    public synchronized void get() { if (!this.flag) { try { this.wait(); } catch (InterruptedException e) { e.printStackTrace(); } } System.out.println(name + ":::" + age); this.flag = false; this.notify(); } } // 模擬生產者線程類
class SetStudent implements Runnable { // 共享資源s
    private Student s; private int x = 0; public SetStudent(Student s) { this.s = s; } @Override public void run() { while (true) { if (x % 2 == 0) { s.set("郭靖", 27); } else { s.set("黃蓉", 18); } x++; } } } // 模擬消費者線程類
class GetStudent implements Runnable { // 共享資源s
    private Student s; public GetStudent(Student s) { this.s = s; } @Override public void run() { while (true) { s.get(); } } } // 測試類
public class Demo03{ public static void main(String[] args) { Student s = new Student(); SetStudent ss = new SetStudent(s); GetStudent gs = new GetStudent(s); Thread t1 = new Thread(ss, "生產者"); Thread t2 = new Thread(gs, "消費者"); t1.start(); t2.start(); } }

面試題4: 現有的程序代碼模擬產生了16個日志對象,並且需要運行16秒才能打印完這些日志,請在程序中增加4個線程去調用parseLog()方法來分頭打印這16個日志對象,程序只需要運行4秒即可打印完這些日志對象。

原始代碼如下:

public class Test {
        
        public static void main(String[] args){
            
            System.out.println("begin:"+(System.currentTimeMillis()/1000));
            /*模擬處理16行日志,下面的代碼產生了16個日志對象,當前代碼需要運行16秒才能打印完這些日志。
            修改程序代碼,開四個線程讓這16個對象在4秒鍾打完。
            */
            for(int i=0;i<16;i++){  //這行代碼不能改動
                final String log = ""+(i+1);//這行代碼不能改動
                {
                         Test.parseLog(log);
                }
            }
        }
        
        //parseLog方法內部的代碼不能改動
        public static void parseLog(String log){
            System.out.println(log+":"+(System.currentTimeMillis()/1000));
            
            try {
                Thread.sleep(1000);
            } catch (InterruptedException e) {
                e.printStackTrace();
            }        
        }
        
    }

改寫代碼如下:

package com.wang.reflect;

import java.util.concurrent.ArrayBlockingQueue;
import java.util.concurrent.BlockingQueue;

public class Demo03 {
    
    public static void main(String[] args){
        //定義一個線程共享的隊列容器,可以使得數據由隊列的一端輸入,從另外一端輸出
        final BlockingQueue<String> queue=new ArrayBlockingQueue<String>(16);
        for(int i=0;i<4;i++){
            new Thread(new Runnable(){

                @Override
                public void run() {
                    while(true){
                        try {
                            parseLog(queue.take());
                        } catch (InterruptedException e) {
                            e.printStackTrace();
                        }
                    }
                }
                
            }).start();
        }
        
        System.out.println("begin:"+(System.currentTimeMillis()/1000));
        /*模擬處理16行日志,下面的代碼產生了16個日志對象,當前代碼需要運行16秒才能打印完這些日志。
        修改程序代碼,開四個線程讓這16個對象在4秒鍾打完。
        */
        for(int i=0;i<16;i++){  //這行代碼不能改動
            final String log = ""+(i+1);//這行代碼不能改動
            {
                     try {
                        queue.put(log);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
            }
        }
    }
    
    //parseLog方法內部的代碼不能改動
    public static void parseLog(String log){
        System.out.println(log+":"+(System.currentTimeMillis()/1000));
        
        try {
            Thread.sleep(1000);
        } catch (InterruptedException e) {
            e.printStackTrace();
        }        
    }
    
}

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM