这是我在看一本关于java多线程编程的电子书时,觉得该书的讲述和所举的程序例子比较经典,能够很快的让读者理解其内容。因此我通过自己的话来将其中的部分内容进行总结一下。
我们知道,计算机中的运行的组织单位是进程,而为了提高计算机的执行效率,进一步提高计算机并发执行能力和运行效率,引入了轻量级的进程,即线程。 在java语言中,对多线程进行编程是很方便的,因为java提供的API能够让编程人员很方便的通过高级语言来进行多线程编程。java的API中主要是通过继承Thread类和实现Runnable接口两种方式来实现多线程编程。
首先来看一个简单的java程序,该程序中通过实现Runnable接口,实现了两个线程的并发。
public class firstThread {
public static void main(String[] args){
new Thread(new Runnable(){
public void run(){
int i =0;
while(i<100){
System.out.println("thread1:"+i++);
}
}
}).start();
int i=100;
while(i>0){
System.out.println("thread2:"+i--);
}
}
}
这是在eclipse中运行的结果,两个线程交替运行的结果展示。其实这个程序的逻辑很清晰和简单,在main函数中,是一个主函数的线程,然后通过实现runnable接口,又生成了一个新的线程,因此从整体上看,该程序的进程具有两个同时并发的线程。而我们多次运行该程序,可以发现改程序的执行结果并不是每次都一样,有时,直到一个线程运行完后,第二个线程才开始运行。因此这就涉及到了操作系统底层的内容,我们知道操作系统通常实际同一时刻只能运行一个模块(多核技术除外),因此调度运行资源的的分配,一个线程生成了,并不能马上就运行,因为还需要等待操作系统分配运行所需要的资源。因此每次调度的时间点不同,和分配的时间片长度不同,导致了运行结果的不同。
下面同样是实现两个线程并发执行的程序是通过继承Thread类来实现的,其运行结果和实现Runnable接口是一样的。
public class firstThread extends Thread{
public void run(){
int i=0;
while(i<100){
System.out.println("i:"+i++);
}
}
public static void main(String[] args) {
firstThread thread = new firstThread();
thread.start();
int i=0;
while(i<100){
System.out.println("j:"+i++);
}
}
}
下面看一个多线程编程的简单的应用,一个简单的银行叫号系统,模拟银行窗口叫号服务的模型。首先看程序代码:
class TicketWindows implements Runnable{
private int max_value =0;
public void run(){
while(true){
if(max_value>100)
break;
System.out.println(Thread.currentThread().getName()+":"+max_value++);
}
}
}
public class bank{
public static void main(String[] args){
TicketWindows tw2 = new TicketWindows();
Thread t1 = new Thread(tw2);
Thread t2 = new Thread(tw2);
Thread t3 = new Thread(tw2);
t1.start();
t2.start();
t3.start();
}
}
在以上代码中ticketWindows类实现了Runnable接口,并实现了其run()方法。在bank类中,首先生成了一个TicketWindows类,接着分别为该类的一个实例创建了三个线程,然后通过start()方法,启动三个线程。分析该小程序,一共具有四个线程,主函数一个线程,和所生成的三个窗口线程。下面是该程序在eclipse中运行的结果。
我所截取的是有线程交替输出的部分。说到这里,如果我们多次运行这些程序,会发现折现程序的执行结果不是那么的令人满意,比如线程的交替并不是那么明显,经常出现,一个线程执行很长时间,然后才交换到另一个线程的执行。这是由于这些只是最基本的实现了多线程的程序,还有很多线程编程方面的限制和技术没有使用,比如线程间的通信,同步等,以及操作系统方面的知识。