- 单线程
package com;
public class SingletonThread {
public static void main(String[] args) {
// TODO Auto-generated method stub
Thread thread = Thread.currentThread();
thread.setName("单线程");
System.out.println(thread.getName()+"正在运行");
for (int i = 0; i < 10; i++) {
System.out.println("线程正在休眠:"+i);
try {
thread.sleep(500);
} catch (Exception e) {
// TODO: handle exception
e.printStackTrace();
System.out.println("线程出现错误!");
}
}
}
}
- 多线程
public class ThreadImpl {
public static void main(String[] args) {
Thread t1 = new ThreadTest("t1", 1000);
Thread t2 = new ThreadTest("t2", 20000);
Thread t3 = new ThreadTest("t3", 300000);
t1.start();
t2.start();
t3.start();
}
}
class ThreadTest extends Thread{
private String name;
private int ms;
public ThreadTest(String name, int ms) {
this.name = name;
this.ms = ms;
}
public void run(){
try {
sleep(ms);
} catch (Exception e) {
// TODO: handle exception
<span style="white-space:pre"></span>System.out.println("线程中断异常");
}
System.out.println("名称为:"+name+",线程休眠:"+ms+"毫秒");
}
}
结果:
名称为:t1,线程休眠:1000毫秒
名称为:t2,线程休眠:20000毫秒
名称为:t3,线程休眠:300000毫秒
从上面的代码中可看出,程序启动时总是会自动调用main()方法执行主线程,因此main()是创建和启动程序的地方,首先创建t1、t2、t3三个线程并传入了相应的参数,程序运行到t1.start(); 启动线程并自动调用run()方法,在run()方法中,sleep(1000)这个方法使t1线程暂停停止运行1000毫秒,之后线程才可以恢复运行,在t1休眠的状态里,把执行权交给t2,而不是等t1恢复运行后再让t2运行。 由此可以得出:一个线程对象只能启动一个线程,无论你调用多少遍start()方法,结果只有一个线程。
2、实现Runnable接口,并重写run方法
public class RunnableTest {
public static void main(String[] args) {
Runnable runnable=new MyThread();
new Thread(runnable).start();
new Thread(runnable).start();
new Thread(runnable).start();
new Thread(runnable).start();
}
public static class MyThread implements Runnable{
//车票数量
private int tickets=100;
public void run() {
while(tickets>0){
System.out.println(Thread.currentThread().getName()+"卖出第 【"+tickets--+"】张火车票");
}
}
}
}
从结果上看每个票号都被打印了四次,即四个线程各自卖各自的100张票,而不去卖共同的100张票。这种情况是怎么造成的呢?我们需要的是,多个线程去处理同一个资源,一个资源只能对应一个对象,在上面的程序中,我们创建了四个ThreadTest对象,就等于创建了四个资源,每个资源都有100张票,每个线程都在独自处理各自的资源。
实现Runnable接口相对于继承Thread类来说,有如下显著的好处:
(1)适合多个相同程序代码的线程去处理同一资源的情况,把虚拟CPU(线程)同程序的代码,数据有效的分离,较好地体现了面向对象的设计思想。 (2)可以避免由于Java的单继承特性带来的局限。我们经常碰到这样一种情况,即当我们要将已经继承了某一个类的子类放入多线程中,由于一个类不能同时有两个父类,所以不能用继承Thread类的方式,那么,这个类就只能采用实现Runnable接口的方式了。 (3) 有利于程序的健壮性,代码能够被多个线程共享,代码与数据是独立的。当多个线程的执行代码来自同一个类的实例时,即称它们共享相同的代码。多个线程操作相 同的数据,与它们的代码无关。当共享访问相同的对象是,即它们共享相同的数据。当线程被构造时,需要的代码和数据通过一个对象作为构造函数实参传递进去, 这个对象就是一个实现了Runnable接口的类的实例。