Mengapa lulus objek subkelas antara muka Runnable kepada pembina Thread?
巴扎黑
巴扎黑 2017-06-12 09:19:22
0
3
1593

Selain itu, berbanding dengan benang, selain daripada warisan, bagaimanakah kebebasan kod dan data dicerminkan dalam runnable? Seperti yang ditulis pada beberapa blog, thread tidak boleh berkongsi sumber, tetapi runnable boleh berkongsi sumber Bukankah cukup untuk menukar pembolehubah dalam thread kepada statik? Sama seperti apa yang dikatakan artikel berikut http://blog.csdn.net/uudou/ar...

巴扎黑
巴扎黑

membalas semua(3)
漂亮男人

Nampaknya ia tidak banyak kaitan dengan data saya rasa Runnable mempunyai dua faedah:

  1. Selepas melaksanakan Runnable, anda boleh membuka thread untuk dijalankan (biasanya menggunakan executorService.exec(command),挫一点也可以用new Thread(command).start()),也可以不开线程阻塞式的跑(直接调用command.run()

    );
  2. Java 1.8 dan lebih baru boleh dijalankan dengan Lambda, contohnya:

  3. new Thread(() -> {
        // Do something
    }).start();
    
    
    
代言

Runnable的好处是各种场景都可以用,比如你可以让任何一个Class implements Runnable,但是extends ThreadTerdapat beberapa batasan kerana warisan tunggal Java, ia tidak boleh digunakan dalam beberapa senario.

Peter_Zhu

Jawapan:

Masalah ini dianggap masalah reka bentuk.

Sebab mengapa Thread dan Runnable dipisahkan adalah untuk memisahkan sepenuhnya "proses penciptaan" thread daripada "logic pelaksanaan" thread.

Dalam erti kata lain:
Proses penciptaan thread ialah "kod";
Logik pelaksanaan thread ialah "data"

Ini kedengaran agak mengelirukan, bukankah semuanya kod JAVA? Mengapa kod menjadi data semula?

Kami tidak terjerat dalam konsep ini, saya fikir kita boleh memikirkan isu ini secara terbalik dan memberi contoh untuk menggambarkan masalah.

Proses perbincangan:

Sebagai contoh, saya ingin mereka bentuk program single-thread ini perlu menyelesaikan dua tugasan:

1. Cetak ayat hello world
2. Kira jumlah dua nombor int a dan int b dan keluarkan;

Nota: Apakah pelaksanaan 1? Atau 2? Ia ditentukan oleh parameter n, n ialah nombor rawak...

Untuk melaksanakan dua tugasan ini dalam urutan yang sama, kita boleh menulis kod seperti ini:

float n = (float)Math.random();

int a = 1;
int b = 1;

Thread t = new Thread() {
    @Override
    public void start() {
        if (n >= 0.5f) {
            System.out.println("hello world");
        } else {
            System.out.println(a + b);
        }
    }
};

t.start();
Kod di atas memang boleh menyelesaikan tugas, tetapi masalahnya ialah kita mengelirukan "proses penciptaan" dan "logik perniagaan" benang...

Ini tidak bagus. Dengan cara ini, dari peringkat sistem pengendalian, proses penciptaan benang sebenarnya sangat rumit!

Bahasa Java merangkumkan kerumitan ini di luar penglihatan Walaupun kod tersebut hanyalah kelas Thread dan nampaknya tiada ambang untuk memanggilnya, proses penciptaan Thread masih sangat rumit dan menggunakan sumber.

Kembali kepada perniagaan, kini saya menambah keperluan kecil lagi Selain 1 dan 2 sebelumnya, saya juga menambah 3 untuk memaparkan cap masa semasa sistem.

Jadi tugasnya menjadi:

1. Cetak ayat hello
2
Perhatikan bahawa pada masa ini kita perlu mengubah suai proses penciptaan Thread, iaitu mengubah suai fungsi mula:

float n = (float)Math.random();

int a = 1;
int b = 1;

Thread t = new Thread() {
    @Override
    public void start() {
        if (n >= 0.33f) {
            System.out.println("hello world");
        } else if (n >= 0.66f) {
            System.out.println(a + b);
        } else {
            System.out.println(System.currentTimeMillis()); // 这里是新增的语句
        }
    }
};

t.start();
Perbincangan ini tamat, mari kita amati dengan teliti...Sebenarnya:

Thread t = new Thread() {
    @Override
    public void start() {
        // ...
    }
}
Bahagian kod ini kekal tidak berubah, hanya kod dalam fungsi mula diubah suai apabila keperluan berubah.

Jadi bolehkah kita membungkus bahagian kandungan yang diubah ini menjadi antara muka? ?

Ini sepatutnya idea yang bagus!

Thread t = new Thread() {
    private Runnable runnable; // 这里定义一个 Runnable 类型的成员

    @Override
    public void start() {
        if (null != this.runnable) {
            runnable.run(); // 在这里用接口来把频繁变化的业务逻辑从线程代码里给拿出去,只调用 run 函数
        }
    }
}
Saya tidak tahu sama ada anda faham sepenuhnya sekarang? :D

Haha, bukankah kelas Thread Java hanya menyediakan pembina dengan parameter Runnable?

Kami meletakkan kod perniagaan ke dalam kelas pelaksanaan antara muka Runnable:

class BizLogicRun implements Runnable {
    @Override
    public void run() {
        float n = (float)Math.rand();

        int a = 1;
        int b = 1;

        if (n >= 0.33f) {
            System.out.println("hello world");
        } else if (n >= 0.66f) {
            System.out.println(a + b);
        } else {
            System.out.println(System.currentTimeMillis()); // 这里是新增的语句
        }
    }
}
Jadi akhirnya, kita boleh memanggilnya seperti ini:

Thread t = new Thread(new BizLogicRun());
t.start();
Ini melengkapkan pemisahan lengkap "proses penciptaan" dan "logik perniagaan" utas! "Perpecahan" ini juga membuka jalan untuk teknologi Java Thread Pool.

Sejujurnya, Thread t = new Thread() { ... } dalam kod sampel cukup mudah, tetapi mencipta Thread dalam kumpulan thread tidaklah semudah itu.

Jadi "split" sangat diperlukan!

Selain itu, bolehkah kita bayangkan:

class PoolRun implements Runnable {
    List<Runnable> runnableList;
}
Apakah yang berlaku jika kelas pelaksanaan Runable mengandungi senarai Runnable?

Ringkasan:

1. Tujuan menggunakan antara muka Runnable adalah untuk memisahkan sepenuhnya "proses penciptaan" daripada "logik pelaksanaan" thread
2 ;
3 Dalam Semasa perbincangan, kami beralih dari konkrit kepada abstrak
4 Kod yang saya berikan dalam contoh ini memang agak mudah, tetapi saya harap ia dapat menjelaskan masalahnya dengan jelas;

Baiklah, di atas adalah jawapan saya untuk soalan ini, saya harap ia akan membantu anda.

Muat turun terkini
Lagi>
kesan web
Kod sumber laman web
Bahan laman web
Templat hujung hadapan