Thread与Runnable两种多线程方式

时间:2022-05-17 14:10:33
  • 多线程是Java一大特点,如果没有多个处理器,在逻辑上还是单核处理器在执行,如果在语言层面给予支持多核处理器可以在微观上同时的执行程序,Intel处理器支持超线程技术,例如双核四线程的i3甚至是8核16线程的i7处理器,还有面向服务器的xeon处理器,服务器注重的可靠性与稳定性因此并不会把单核的主频提升太高,但是对多线程的支持是解决高并发与资源共享的好方法。
  • 线程是进程的子集,也是操作系统调度的最小单位,一个或则多个线程完成一个进程。线程对应的JVM里的栈。启动一个线程总是先有栈,当生成对象的时候才会在堆上创建对象。
  • java里启动多线程有Thread与实现Runable接口的两种方法,参考网上的相关教程,这次写点入门的笔记。
  • 执行线程,可以用run和start两个方法,run并没有启动新线程,只是顺序的执行了run方法。start方法会启动新的线程,而且start方法可以调用操作系统的底层函数,达到交替执行的目的。
class MyThread extends Thread
{

//创建一个Thread的子类
String name;
@Override
public void run()
{
for(int i = 0;i < 10;i ++)
{
System.out.println(name + " " + i);
}
}
MyThread(String name)
{
this.name = name;
}
}

测试:

        /*
* run与start执行方式的区别
*/

MyThread m1 = new MyThread("micro");
MyThread m2 = new MyThread("xiaoma");
m1.start();//启动新线程,可实现交替执行

m2.start();//一旦调用start方法,JVM会自动找到run方法去执行,可调用底层函数
m1.run();//如果直接执行run的方式,m1执行完再执行m2
m2.run();

参考jdk源码Thread本身就实现了Runnable接口,Thread里有一个Thread(Runnable target)方法,可以传入Runnable的实现类,然后去执行run或则start方法。

class MyThread2 implements Runnable
{

String name;
MyThread2(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);
}
}
}

测试:

        /*
* 在实际开发中,很少直接使用继承Thread的方式去启动多线程
* 而是使用实现Runnable接口
*/

System.out.println("Thread启动Runnable实现类");
MyThread2 m3 = new MyThread2("micro2");
MyThread2 m4 = new MyThread2("xiaoma2");
new Thread(m3).start();
new Thread(m4).start();
  • 比较这两种方法,一般使用Runnable接口传入Thread的方法要多些,这样克服了单继承的局限性还可以达到共享变量的效果,关于共享变量,参考一个卖票的教程,例子有点小问题,但是在回帖中大家都指正了错误:
    如果用Thread启动线程实现卖票:
    System.out.println("卖票资源无法共享");
ThreadTicket m5 = new ThreadTicket();
ThreadTicket m6 = new ThreadTicket();
m5.start();//start有调用底层本地方法可以合理交替执行run方法
m6.start();//两个线程,每个线程售票10张
//此售票方法,每个卖出了10张票,无法达到资源共享的目的
class ThreadTicket extends Thread
{

private int ticket = 10;
@Override
public void run()
{
while(true)
{
if(ticket > 0)
{
System.out.println("此时剩余票:"+ticket);
ticket --;
}
else
{
break;
}
}
System.out.println("票数为"+ticket+" 售票结束");
}
}

通过实现Runnable接口的方法:

        /*
* 如果使用Runnable接口,就可以实现共享
*/

ThreadTicket2 m7 = new ThreadTicket2();
new Thread(m7).start();
new Thread(m7).start();//虽然两个线程,但一共售出了10张票
//Runnable接口实现资源共享的目的
class ThreadTicket2 implements Runnable
{

private int ticket = 10;
@Override
//注意此处需要加锁控制同步,保证线程安全
public synchronized void run() {
// TODO Auto-generated method stub
while(true)
{
if(ticket > 0)
{
System.out.println("此时剩余票数:"+ticket);
ticket --;
}
else
{
break;
}
}
System.out.println("剩余票数为"+ticket+" 停止售票");
}
}