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;
@Override
public 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;
}
@Override
public 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;
}
@Override
public 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();
}
}