所谓
线程,是进程的一部分,一个线程可以单独的执行一项任务,比如一个客户机连接上服务器,我们就启动一个线程来管理这个用户,多个客户机就启动多个线程同时进行管理,线程之间可以进行信息的交换。
使用Java线程时,一般将线程视为一个对象,通常为类Thread对象,或者
接口Runnable对象。但是无论是继承类Thread还是实现接口Runnable最终其实都要使用到Thread类及其方法。既然如此为什么我们不直接继承Thread,还需要Runnable的存在呢,原因是一般继承了Thread的类不能再继承其他类,但是实现接口Runnable是没有这个
限制的。
通过以上分析,在JAVA中使用线程就很明了了,使用线程有俩种方法:
一、直接用一个类继承Thread类,调用该类的Start方法就可以启动线程
二、创建一个类实现接口Runnable,以该类的对象作为参数传递给Thread
构造函数创建一Thread对象,调用Start方法就可以启动线程。
其实 Thread类有很多方法可以使用,常用的有以下几个
start():启动线程
stop():停止线程
sleep(int n):线程暂停n秒
run():调用start方法时该方法执行
在线程中用到比较多的还有
关键字:synchronized。该关键字的作用是避免多个线程同时对某个数据对象进行进行访问,造成数据的混乱。
我们以生产者/
消费者的
例子来进一步了解一下线程
生产者:
import java.util.ArrayList;
public
class Tproduct extends Thread{
private ArrayList<Apple> al;
public Tproduct(ArrayList al) {
this.al = al;
}
public void run() {
super.run();
int name = 0;
while (true) {
try {
synchronized (al) {
if (al.size() == 0) {
Apple c = new Apple("苹果" + name);
al.add(c);
System.out.println("收获一个" + c.name);
name++;
al.notify(); //如果收获一个苹果,就通知一下
} else {
}
}
Thread.sleep(1000);
} catch (InterruptedException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
}
}
消费者:
import java.util.ArrayList;
public class Tcustom extends Thread{
private ArrayList<Apple> al;
public Tcustom(ArrayList al) {
this.al = al;
}
public void run() {
super.run();
while (true) {
synchronized (al) {
if (al.size() > 0) {
Apple c = (Apple) al.remove(0);
System.out.println("吃了" + c.name);
} else {
// 如果没有苹果 就等待
try {
al.wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
}
}
}
}
产品:
public class Apple {
public Apple(String name) {
this.name = name;
}
public String name;
}
程序执行:
import java.util.ArrayList;
public class Text {
private static ArrayList<Apple> al = new ArrayList<Apple>();
public static void main(String args[]) {
Tcustom tc = new Tcustom(al);
Tproduct tp = new Tproduct(al);
tc.start();
tp.start();
}
}
以上程序中使用了俩个线程,分别模拟生产者和消费者,不停的进行生产和消费。每生产一个产品就消费掉他,使用
同步避免了俩个线程对数组
队列同时访问。