JAVA實習找工作——多線程

線程的創建方式一

/**
 * 從創建多線程的方式一
 * 1.創建一個類繼承Thread
 * 2.重寫Thread類的run方法-方法體的內容就是你這個線程想要完成的任務
 * 3.在主方法中new類的對象
 * 4.調用這個對象的start方法
 * 此時主線程main在運行,我們自定義的線程也在運行
 */
package com.eight;

/**
 * 從創建多線程的方式一
 * 1.創建一個類繼承Thread
 * 2.重寫Thread類的run方法-方法體的內容就是你這個線程想要完成的任務
 * 3.在主方法中new類的對象
 * 4.調用這個對象的start方法
 * 此時主線程main在運行,我們自定義的線程也在運行
 */
public class Demo1 {
    public static void main(String[] args) {
        //這是第一個線程
        MyThread t1 = new MyThread();
        t1.setName("線程1");
        t1.start();
        //這是第二個線程
        MyThread t2 = new MyThread();
        t2.setName("線程2");
        t2.start();


        System.out.println("hello");
    }
}

class MyThread extends Thread{
    @Override
    public void run() {
        for (int i=1;i<=100;i++){
            if (i%2 == 0)
                System.out.println(this.getName()+":"+i);
        }
    }
}

線程的創建方式二

/**
 * 創建多線程的方式2
 * 1.創建一個類ThreadA 實現接口Runnable
 * 2.ThreadA中實現run方法
 * 3.主線程中new ThreadA的對象a
 * 4.t1 = new Thread(a),將a傳進去
 * 5.調用t1的start方法
 */
package com.eight;

/**
 * 創建多線程的方式2
 * 1.創建一個類ThreadA 實現接口Runnable
 * 2.ThreadA中實現run方法
 * 3.主線程中new ThreadA的對象a
 * 4.t1 = new Thread(a),將a傳進去
 * 5.調用t1的start方法
 */

class ThreadA implements Runnable{

    @Override
    public void run() {
        for (int i=1;i<=100;i++){
            if (i%2 == 0)
                System.out.println(Thread.currentThread().getName()+":"+i);
        }
    }
}
public class Demo2 {

    public static void main(String[] args) {
        ThreadA a = new ThreadA();

        //這是第一個線程
        Thread t1 = new Thread(a);
        t1.setName("線程1");
        t1.start();
        //這是第二個線程
        Thread t2 = new Thread(a);
        t2.setName("線程2");
        t2.start();
    }
}

線程的生命週期

線程的同步機制

面試題:synchronized 與 Lock的異同?
相同:二者都可以解決線程安全問題
不同:synchronized機制在執行完相應的同步代碼以後,自動的釋放同步監視器,Lock需要手動的啓動同步(lock(),同時結束同步也需要手動的實現(unlock())

線程通信

線程通信涉及到的三個方法:
* wait():一旦執行此方法,當前線程就進入阻塞狀態,並釋放同步監視器。
* notify():一旦執行此方法,就會喚醒被wait的一個線程。如果有多個線程被wait,就喚醒優先級高的那個。
* notifyAll():一旦執行此方法,就會喚醒所有被wait的線程。

面試題:sleep() 和 wait()的異同?
相同點:一旦執行方法,都可以使得當前的線程進入阻塞狀態。
不同點:1)兩個方法聲明的位置不同:Thread類中聲明sleep() , Object類中聲明wait()
              2)調用的要求不同:sleep()可以在任何需要的場景下調用。 wait()必須使用在同步代碼塊或同步方法中
              3)關於是否釋放同步監視器:如果兩個方法都使用在同步代碼塊或同步方法中,sleep()不會釋放鎖,wait()會釋放鎖。

JDK5新增的線程創建方式——實現Callable接口

實現Callable接口。 --- JDK 5.0新增
//1.創建一個實現Callable的實現類
class NumThread implements Callable{
    //2.實現call方法,將此線程需要執行的操作聲明在call()中
    @Override
    public Object call() throws Exception {
        int sum = 0;
        for (int i = 1; i <= 100; i++) {
            if(i % 2 == 0){
                System.out.println(i);
                sum += i;
            }
        }
        return sum;
    }
}


public class ThreadNew {
    public static void main(String[] args) {
        //3.創建Callable接口實現類的對象
        NumThread numThread = new NumThread();
        //4.將此Callable接口實現類的對象作爲傳遞到FutureTask構造器中,創建FutureTask的對象
        FutureTask futureTask = new FutureTask(numThread);
        //5.將FutureTask的對象作爲參數傳遞到Thread類的構造器中,創建Thread對象,並調用start()
        new Thread(futureTask).start();

        try {
            //6.獲取Callable中call方法的返回值
            //get()返回值即爲FutureTask構造器參數Callable實現類重寫的call()的返回值。
            Object sum = futureTask.get();
            System.out.println("總和爲:" + sum);
        } catch (InterruptedException e) {
            e.printStackTrace();
        } catch (ExecutionException e) {
            e.printStackTrace();
        }
    }

}

如何理解實現Callable接口的方式創建多線程比實現Runnable接口創建多線程方式強大?
* 1. call()可以返回值的。
* 2. call()可以拋出異常,被外面的操作捕獲,獲取異常的信息
* 3. Callable是支持泛型的

JDK5新增的線程創建方式——線程池技術

public class ThreadPool {
    //主方法
    public static void main(String[] args) {
        //1. 提供指定線程數量的線程池
        ExecutorService service = Executors.newFixedThreadPool(10);
        //這個ExecutorService 其實是一個接口,所以service的實現類是ThreadPoolExecutor,如下是可以強轉的                          
        ThreadPoolExecutor service1 = (ThreadPoolExecutor) service;

        //設置線程池的屬性
        //System.out.println(service.getClass());
        //service1.setCorePoolSize(15);
        //service1.setKeepAliveTime();


        //2.執行指定的線程的操作。需要提供實現Runnable接口或Callable接口實現類的對象
        //線程池只是給我們提供一個一個的線程,具體線程做什麼任務還需要我們自己編寫
        service.execute(new NumberThread());//適合適用於Runnable
        service.execute(new NumberThread1());//適合適用於Runnable

        //service.submit(Callable callable);//適合使用於Callable
        //3.關閉連接池
        service.shutdown();
    }

}




class NumberThread implements Runnable{

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

class NumberThread1 implements Runnable{

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

 

 

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