JavaSE-Runnable接口实现多线程
因为Java中不支持类的多继承,所以在使用继承Thread类来实现多线程时,存在继承局限,所以Java中又提供了另一种多线程的实现模式:Runnable接口实现多线程。
首先看一下Runnable接口的源码
@FunctionalInterface
public interface Runnable {
/**
* When an object implementing interface <code>Runnable</code> is used
* to create a thread, starting the thread causes the object's
* <code>run</code> method to be called in that separately executing
* thread.
* <p>
* The general contract of the method <code>run</code> is that it may
* take any action whatsoever.
*
* @see java.lang.Thread#run()
*/
public abstract void run();
}
然后我们来实现一个Runnable接口
class My_Runnable implements Runnable{
@Override
public void run() {
System.out.println("My_Runanble的run方法");
}
}
public class Main{
public static void main(String[] args){
Runnable New_Runnable = new My_Runnable();
Thread thread = new Thread(New_Runnable);
thread.start();
System.out.println("运行结束");
}
}
实现了Runnable接口之后,我们应该将它作为Thread类的构造参数。Thread类的构造方法有八种。
Thread(); | 分配新的Thread对象 |
Thread(String name); | 分配新的Thread对象 |
Thread(Runnable target); | 分配新的Thread对象 |
Thread(Runnable target, String name); | 分配新的Thread对象 |
Thread(ThreadGroup group, Runnable target); | 分配新的Thread对象 |
Thread(ThreadGroup group, Runnable target, String name); | 分配新的Thread对象,将target作为其运行对象,将指定的name作为其名称,并作为group所引用的线程组的一员。 |
Thread(ThreadGroup group, String name); | 分配新的Thread对象 |
Thread(ThreadGroup group, Runnable target, string name, long StackSize); | 分配新的Thread对象,将target作为其运行对象,将指定的name作为其名称,并作为group所引用的线程组的一员,并具有指定的堆栈大小。 |
在这8个构造方法中,有Thread(Runnable target)和Thread(Runnable target, String name)可以直接传递Runnable接口,就像上面的例子一样,上面的例子使用了Thread(Runnable target)构造方法。
还有一点就是:Thread类也是实现了Runnable接口的类,所以在Thread类的构造中才可以接收Runnabe接口的对象。
因为Runnable接口只含有一个抽象方法,是函数式接口,我们也可以用lamdba表达式来进行Runnable接口的对象创建。
public class Main{
public static void main(String[] args){
Runnable New_Runnable = () -> System.out.println("使用lamdba表达式创建的接口实现对象");
Thread thread = new Thread(New_Runnable);
thread.start();
System.out.println("运行结束");
}
}
因为Runnable接口实现多线程可以避免Thread类实现多线程的继承局限性,所以Runnablea接口要更好一些,除此之外,这两种实现方式还有一些其他的区别。
首先,我有在上面提过:Thread类也实现了Runnable接口,所以Thread的构造函数不仅可以传入Runnable接口的实现对象,也可以传入一个Thread类的对象,这样就可以把一个Thread的对象的交给其他的线程对象进行调用。
其次,有关线程类的继承结构,使用了代理设计模式:对于Runnable接口,Thread类继承于它,我们使用的新线程也是Runnable接口的实现类,所以在这里Thread类是辅助实现的代理类(Proxy),而我们的新线程类(假设是My_Thread)是主业务的实现类。
class My_Runnablle implements Runnable{
private int tacket = 10;
@Override
public void run() {
while (tacket>0){
System.out.println(Thread.currentThread().getName()+"还有"+this.tacket--+"张票");
}
}
}
public class Main{
public static void main(String[] args){
Runnable New_Runnable = new My_Runnablle();
new Thread(New_Runnable,"新线程1").start();
new Thread(New_Runnable,"新线程2").start();
}
}
Runnable接口实现多线程可以更好的描述资源共享的情形。例如这段代码的输出结果为。
这就实现了两个线程共享一份资源的情况。
对于Runnable接口实现多线程我就先总结到这里,后续可能会有补充。
下一篇: 生产者消费者案例