java thread programming,新手编程:Java多线程中Thread与Runnable的区别

Java多线程中Thread与Runnable的区别

定义

extends Thread

子类继承Thread具备多线程能力,可以实现多线程;启动线程的方法:①创建子类对象 ②对象名.start();不建议使用:避免多线程OOP单继承的局限性(OOP:Object Oriented Programming,面向对象的编程、类似的还有OOD(面向对象的设计),OOA(面向对象的分析));implements Runnable

实现Runnable接口具有多线程能力,可以实现多线程启动线程的方法:①创建子类对象 ②new Thread(对象).strart();推荐使用:避免OOP单继承的局限性,方便被同一个对象多次使用;实际上所有的多线程代码都是通过执行Thread的start()方法来运行的。所以不管是继承Thread类还是实现Runnable接口来实现多线程,最终都是通过Thread对象的API来控制线程的,因此熟悉Thread类的API是进行多线程编程的基础。(点击查看什么是API)

示例

继承Thread实现多线程1

package 多线程1;

public class TestThread1 extends Thread {

@Override

public void run() {

for (int i = 0; i < 20; i++) {

System.out.println("子线程正在执行..."+i);

}

}

public static void main(String[] args) {

TestThread1 testThread1 = new TestThread1();

testThread1.start();

for (int i = 0; i < 500; i++) {

System.out.println("主线程正在执行..."+i);

}

}

}

上述示例执行后可以看到:主线程和子线程的执行顺序本该是“先执行子线程、再执行主线程”,事实上却是主线程和子线程交替执行(无法人为控制,由CPU调度执行),这便是多线程的特征;

dc16c89bbff36aa1cedb0fdb8ea748b3.png

继承Thread实现多线程2——下载网络图片

package 多线程1;

import org.apache.commons.io.FileUtils;

import java.io.File;

import java.io.IOException;

import java.net.MalformedURLException;

import java.net.URL;

//练习网络下载图片

public class TestThread2 extends Thread {

private String url;

private String name;

public TestThread2(String url,String name){

this.name=name;

this.url=url;

}

@Override

public void run() {

WebDownloader webDownloader = new WebDownloader();

webDownloader.Downloader(url,name);

System.out.println("下载的文件名为 "+name);

}

public static void main(String[] args) {

TestThread2 t1 = new TestThread2("双引号内填网络图片url","p1.jpg");

TestThread2 t2 = new TestThread2("双引号内填网络图片url","p2.jpg");

TestThread2 t3 = new TestThread2("双引号内填网络图片url","p3.jpg");

t1.start();

t2.start();

t3.start();

}

}

//下载器

class WebDownloader{

public void Downloader(String url,String name) {

try {

FileUtils.copyURLToFile(new URL(url),new File(name));

} catch (IOException e) {

e.printStackTrace();

System.out.println("IO错误!");

}

}

}

注:代码中图片为网络上随机寻找

由以上代码也可以看出:下载的三张图片的顺序本应该是"p1-->p2-->p3",事实上执行后发现三张图片的下载顺序是随机的(受CPU自由调度)。

Runnable接口实现多线程1

package 多线程1;

public class TestThread4_Runnable implements Runnable {

@Override

public void run() {

for (int i = 0; i < 10; i++) {

System.out.println("我是小兔子"+i);

}

}

public static void main(String[] args) {

TestThread4_Runnable testThread4_runnable = new TestThread4_Runnable();

Thread thread = new Thread(testThread4_runnable);

thread.start();

for (int i = 0; i < 800; i++) {

System.out.println("但我是一只小脑斧哦~"+i);

}

}

}

上述代码的执行结果也是随机的,无法根据代码的编写顺序来判断执行顺序。

Runnable接口实现多线程2——龟兔赛跑

7dd060ea62dbf4cc37f196dbc6e0452f.png

package 多线程1;

public class Race implements Runnable {

private String winner=null;

@Override

public void run() {

for (int i = 0; i <= 100; i++) {

if(Thread.currentThread().getName().equals("兔子") && i%5==0) { //模拟兔子休息(1ms)

try {

Thread.sleep(1);

} catch (InterruptedException e) {

e.printStackTrace();

}

}

boolean winner = Win(i);

if(winner)

break;

System.out.println(Thread.currentThread().getName() + "跑了" + i + "步");

}

}

public boolean Win(int steps){ //判断比赛是否结束

if(winner!=null)

return true;

else if(steps==100) {

winner = Thread.currentThread().getName();

System.out.println(winner + "已经完成比赛!");

return true;

}

else

return false;

}

public static void main(String[] args) {

Race race = new Race();

new Thread(race,"兔子").start();

new Thread(race,"乌龟").start();

}

}

上述代码模拟了龟兔赛跑,乌龟和兔子“随机跑步”,兔子在中途“频繁”休息,执行结果最终是乌龟成为了winner!

Thread.sleep()方法调用的目的是不让当前线程独自霸占CPU,以留出一定时间给其他线程执行的机会。 实际上所有的多线程代码执行顺序都是不确定的,每次执行的结果都是随机的。

但由于CPU的执行速度非常快,在测试的数量比较少的情况下可能无法看出随机执行的现象!

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值