標籤:
1.在java使用線程的方式有2種:
(1)繼承Thread類
(2)實現Runnable介面
下面用例子來說明:
方式一:
class Test extends Thread{public void run(){Sysout.println("Thread test ...")}}public class ThreadTest{public static void main(String[] args){ Thread t = new Test(); t.start();}}
方式二:
class Test implements Runnable{public void run(){ System.out.println("Runnable test...");}}public class ThreadTest{public static void main(String[] args){Test t = new Test();Thread th = new Thread(t);th.start();}}
牆裂堅毅是用二種方式,由於java中的類都是單繼承,多實現,當一個類繼承其他類時,還想實現多線程,就不能用繼承,只能用實現介面。
2.線程存在一些安全問題
一個購票的執行個體:
class Ticket implements Runnable{private int ticket = 100;@Overridepublic void run() {while(true){if(ticket>0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"---"+ticket--);}}}}public class TicketDemo {public static void main(String[] args) {Ticket ticket = new Ticket();Thread t = new Thread(ticket);Thread t2 = new Thread(ticket);Thread t3 = new Thread(ticket);Thread t4 = new Thread(ticket);t.start();t2.start();t3.start();t4.start();}}
運行後會出現:
0和-1也出現了,這是不應該出現的。
解釋原因:假設現在只有一張票了,被線程1搶到,由於 Thread.sleep(10); 導致其他線程也進入,當Thread-1醒來將票數減去一,當前票數為0,但是當其他線程醒來,再去減一是,票數早已為0,這就是導致票數為0,-1的原因。
怎麼解決? 在操作資料的地方加入同步代碼塊。
public void run() {while(true){synchronized(this){//同步代碼塊if(ticket>0){try {Thread.sleep(10);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"---"+ticket--);}}}}
如果將run方法加上static 同步代碼塊上不能用this,由於類載入的原因,應該使用Ticket.class對象,在類載入的時候,類的位元組碼對象已經存在,但是執行個體對象不存在,需要通過new 關鍵字建立。
下面是一張線程的圖:
最後一個例子是用線程和網路編程結合的一個聊天代碼:(如果兩個用戶端通訊記得修改ip)
package com.core.net;import java.io.BufferedReader;import java.io.IOException;import java.io.InputStreamReader;import java.net.DatagramPacket;import java.net.DatagramSocket;import java.net.InetAddress;class MSend implements Runnable{private DatagramSocket socket;public MSend(DatagramSocket socket){this.socket = socket;}@Overridepublic void run() {BufferedReader reader = null;try { reader = new BufferedReader(new InputStreamReader(System.in));String line = null;while((line = reader.readLine())!=null){if("886".equals(line)){break;} byte[] buf = line.getBytes(); DatagramPacket dp = new DatagramPacket(buf, buf.length, InetAddress.getByName("192.168.23.255"), 8887); socket.send(dp);}} catch (Exception e) {throw new RuntimeException("發送端失敗"); }finally{try {reader.close();} catch (IOException e) {e.printStackTrace();}socket.close();}}}class MRecevice implements Runnable{private DatagramSocket socket;public MRecevice(DatagramSocket socket){this.socket = socket;}@Overridepublic void run() {try {while(true){ byte[] buf = new byte[1024];DatagramPacket dp = new DatagramPacket(buf,buf.length);socket.receive(dp);String ip = dp.getAddress().getHostAddress();String data = new String(dp.getData(),0,dp.getLength());System.out.println(ip+":"+data);}} catch (Exception e) {throw new RuntimeException("接受端失敗");}}}public class ChatDemo {public static void main(String[] args) throws Exception { DatagramSocket send = new DatagramSocket(); DatagramSocket rece = new DatagramSocket(8887); new Thread(new MSend(send)).start(); new Thread(new MRecevice(rece)).start(); }}
java線程總結