Java 是支持多线程的语言。之前也就是知道线程的两种实现方法,知道进程里面还可以分为多个线程,进程将所得的资源让线程来用(来自操作系统),线程是比进程更小的基本单位。多线程是实现并发机制的一种有效手段。多线程是指同时可以运行多个程序段。
public class MyThread extends Thread { //继承Thread类 private String name; public MyThread(String name)//带参的构造函数 { this.name=name; } //重写run 函数 @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<10;i++) { System.out.println(name +"运行,i="+i); } } }; public class ThreadDemo { public static void main(String args[]) { MyThread m1=new MyThread("线程A");//实例化对象 MyThread m2=new MyThread("线程B");//实例化对象 m1.start(); // m2.start(); //调用线程主体 } }
线程的运行是不确定的,哪个线程抢到了CPU,运行哪个线程。每次运行的结果可能不一样。
为什么启动线程不能直接使用run()方法,而必须使用start()方法?
因为多线程的运行需要本机操作系统的支持,在start()方法中,调用了本机操作系统中实现多线程的函数start0(),start0()函数以native关键字定义,native关键字表示调用本机的操作系统函数,多线程的实现需要底层操作系统的支持。
如果一个类通过继承Thread类来实现,那只能调用一次start()方法,如果调用多次就会出现"illeagalThreadStateException"异常。
如果一个类只是通过继承Thread类来实现多线程,则必会受到单继承的局限性影响。所以一般来说,要实现多线程就要实现Runnable接口。
在java 中可以通过实现Runnable 接口的方式实现多线程,Runnable接口中只定义了一个抽象方法;public void run()
public class MyThread_2 implements Runnable {//实现Runnable接口 private String name; //定义属性 public MyThread_2 (String name) //带参的构造函数 { this.name=name; } @Override public void run() { // TODO Auto-generated method stub for(int i=0;i<10;i++) { System.out.println("运行程序"+name+"i="+i); } } };
public Thread(Runnable target);
public Thread(Runnable target,String name);
这两个构造函数方法,都可以接收Runnable子类的实例对象,所以就可以依靠此点启动多线程。
public class RunnableThreadDemo { public static void main(String args[]) { MyThread_2 m1=new MyThread_2("线程A");//实例化MyThread_2对象,即Runnable的实例对象 MyThread_2 m2=new MyThread_2("线程B");//实例化MyThread_2对象,即Runnable的实例对象 Thread t1= new Thread(m1); //Thread类的实例,m1作为参数 Thread t2= new Thread(m2); //Thread类的实例,m2作为参数 t1.start(); //调用Thread 的start()方法启动线程 t2.start(); //调用Thread 的start()方法启动线程 } }
虽然这两种方法都能实现多线程,但相比较之下Runnable接口更好,因为:
1.适合相同代码的程序去处理同一数据,即资源共享
2.避免java带来的单继承的局限性
3.增强代码的健壮性,代码和数据是分开的
两种方式对资源处理的区别,代码