首页 技术 正文
技术 2022年11月12日
0 收藏 613 点赞 4,974 浏览 2854 个字

线程创建、start、run

一、创建线程方式

java创建线程的方式,主要有三种:类Thread接口Runnable接口Callable

1、Thread和Runnable进行比较

他们之间的区别

1、实现Runnable的类更具有健壮性,避免了单继承的局限。

2、Runnable更容易实现资源共享,能多个线程同时处理一个资源。

不过对于共享数据而言,使用继承Thread,同样可以实现多线程同时处理同一个资源。

(1)像网上常写的这种方式当然不能实现共享资源了,因为你已经new了多个对象,每个对象之前当然不共享数据

class PrintNum extends Thread{
public void run(){
//子线程执行的代码
for(int i = 1;i <= 100;i++){
if(i % 2 == 0){
System.out.println(Thread.currentThread().getName() + ":" + i);
}
}
}
}public class TestThread {
public static void main(String[] args) {
PrintNum p1 = new PrintNum("线程1");
PrintNum p2 = new PrintNum("线程2");
p1.start();
p2.start();
}
}

(2)但如果你只new一个对象,难道不能实现多线程吗?其实也是可以的,看如下代码:

public class TicketThread extends Thread{    private int ticket = 10;    public void run(){
for(int i =0;i<10;i++){
//首先主要这个this关键字代表当前对象,而下面因为我只new了TicketThread t1 = new TicketThread();一个对象
//所以这个锁是没有问题,但如果new多个的话用this锁同样会失效,为了安全我们可以用TicketThread.class
synchronized (this){
if(this.ticket>0){
try {
Thread.sleep(100);
System.out.println(Thread.currentThread().getName()+"卖票---->"+(this.ticket--));
} catch (InterruptedException e) {
e.printStackTrace();
} } }
}} public static void main(String[] arg){
TicketThread t1 = new TicketThread();
new Thread(t1,"线程1").start();
new Thread(t1,"线程2").start();
//经常看到晚上说thread不能共享资源,这个用例子说明thread同样可以共享资源。
//为什么它也能共享呢?因为Thread本来就是实现了Runnable,包含Runnable的功能是很正常。
}
}

2、Runnable和Callable区别

两者最大的不同点是:

(1)实现Callable接口的任务线程能返回执行结果;而实现Runnable接口的任务线程不能返回结果;

(2)Callable接口的call()方法允许抛出异常;而Runnable接口的run()方法的异常只能在内部消化,不能继续上抛;

举一个Callable获得返回值小案例

public class CallableImpl implements Callable<String> {    public CallableImpl(String acceptStr) {
this.acceptStr = acceptStr;
}
private String acceptStr;
//Callable是重写call方法
@Override
public String call() throws Exception {
// 任务阻塞 1 秒
Thread.sleep(1000);
return this.acceptStr + " append some chars and return it!";
} public static void main(String[] args) throws ExecutionException, InterruptedException {
//Callable对象实现线程,需要先把对象放入FutureTask对象中,再把FutureTask对象放入Thread对象中
Callable<String> callable = new CallableImpl("my callable test!");
FutureTask<String> task = new FutureTask<>(callable);
long beginTime = System.currentTimeMillis();
// 创建线程
new Thread(task).start();
// 调用get()阻塞主线程,反之,线程不会阻塞
String result = task.get();
long endTime = System.currentTimeMillis();
System.out.println("hello : " + result);
System.out.println("cast : " + (endTime - beginTime) / 1000 + " second!");
}
}
/**
* 运行结果
* hello : my callable test! append some chars and return it!
* cast : 1 second!
*/

 二、操作线程方法

有关生命周期相关的方法,放在下一篇文章中,写,这篇主要讲start()和run()方法

1、start() :它的作用是启动一个新线程。

通过start()方法来启动的新线程,处于就绪(可运行)状态,并没有运行,一旦得到cpu时间片,就开始执行相应线程的run()方法,这里方法run()称为线程体,它包含了要执行的这个线程的内容,run方法运行结束,此线程随即终止。

 2、run():就和普通的成员方法一样,可以被重复调用。

如果直接调用run方法,并不会启动新线程!程序中依然只有主线程这一个线程,其程序执行路径还是只有一条,还是要顺序执行。

 3、start和run区别

(1) start() 可以启动一个新线程,run()不能。

(2) start()不能被重复调用,run()可以。

(3)start()中的run代码可以不执行完就继续执行下面的代码,即进行了线程切换。直接调用run方法必须等待其代码全部执行完才能继续执行下面的代码。

(4)start() 实现了多线程,run()没有实现多线程。

4、getName和setName

  用来得到或者设置线程名称。

5、getPriority和setPriority

  用来获取和设置线程优先级。

6、setDaemon和isDaemon

设置是否为守护线程。

 想太多,做太少,中间的落差就是烦恼。想没有烦恼,要么别想,要么多做。少校【7】

相关推荐
python开发_常用的python模块及安装方法
adodb:我们领导推荐的数据库连接组件bsddb3:BerkeleyDB的连接组件Cheetah-1.0:我比较喜欢这个版本的cheeta…
日期:2022-11-24 点赞:878 阅读:8,960
Educational Codeforces Round 11 C. Hard Process 二分
C. Hard Process题目连接:http://www.codeforces.com/contest/660/problem/CDes…
日期:2022-11-24 点赞:807 阅读:5,484
下载Ubuntn 17.04 内核源代码
zengkefu@server1:/usr/src$ uname -aLinux server1 4.10.0-19-generic #21…
日期:2022-11-24 点赞:569 阅读:6,330
可用Active Desktop Calendar V7.86 注册码序列号
可用Active Desktop Calendar V7.86 注册码序列号Name: www.greendown.cn Code: &nb…
日期:2022-11-24 点赞:733 阅读:6,113
Android调用系统相机、自定义相机、处理大图片
Android调用系统相机和自定义相机实例本博文主要是介绍了android上使用相机进行拍照并显示的两种方式,并且由于涉及到要把拍到的照片显…
日期:2022-11-24 点赞:512 阅读:7,745
Struts的使用
一、Struts2的获取  Struts的官方网站为:http://struts.apache.org/  下载完Struts2的jar包,…
日期:2022-11-24 点赞:671 阅读:4,779