多线程作业 java_java多线程--大作业相关

本文介绍了Java实现多线程的三种方式:继承Thread类、实现Runnable接口和使用Callable/Future。通过实例展示了线程的并发执行、状态管理、同步控制以及线程生命周期。此外,还讲解了线程休眠、join方法和后台线程(Daemon)的使用。
摘要由CSDN通过智能技术生成

大作业是选课系统需要多线程。疯狂学习中。为了避免遗忘以blog记录一下~

首先,并行是真正的同时执行,是多个处理器同时运行多个指令,但是并发只是指在一段时间同时进行,本质上还是有先后顺序的,同一时刻完成的是一个任务

java中使用Thread类来表示线程,所以所有的线程对象都是Thread或者是他的子类。

方法一、定义Thread类的子类,在里面重写run方法,run里面的是线程真正要执行的任务。(run是void函数哦)

但是需要注意,在启动线程的时候要使用start而不是run。如果是调用run会立刻执行,调用start是把他当做线程,根据线程的实际调度情况来执行。

如果你使用了run,那this.getName()返回的是对象而不是线程名(甚至可能返回情况跟刚才是一样的)

但是如果用Thread.currentThread().getName(),这种情况下会发现调用run的并没有产生新的线程,还是main的。

应用过run的已经不是新的了,也不可以再用start(刚新建的可以start)

主线程(也就是main)本身也是一个线程。程序在执行过程中至少会有一个主线程

Thread类本身有静态方法和实例方法,静态方法currentThread直接Thread.currentThread()就可以,getName()这种实例方法使用具体对象调用。也可以使用setName修改名称。(eg:this.setName(String name))

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classFirstThread extends Thread

{private inti;public voidrun()

{for(;i<100;i++)

{

System.out.println(this.getName()+""+i);

}

}public static voidmain(String args[])

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

{

System.out.println(Thread.currentThread().getName()+""+i);if(i==20)

{newFirstThread().start();newFirstThread().start();

}

}

}

}

FirstThread

这里面的i在三个线程里面是独立的,因此结果输出的i是乱序的。

另外,虽然从i=20开始启动两个新的线程,但是顺序仍然是不确定的,(在本次执行中,main70多才出现Thread0)

thread0和thread1顺序也是不稳定的

thread010是thread0的,thread10是在thread1里面的0号。(两者不是一一交替进行的,具有一定的随机性,这也是在真正的多线程中需要锁和信号量的主要原因。)

方法二、通过Runnable接口创建线程类

这里面创建出来的并不是真正的线程类,新建的时候还是要new Thread的,这里面在使用同一个SecondThread建出来的thread,公用私有参数的(同样的理由不能用this指定thread,要用静态类Thread下的currentThread)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

public classSecondThread implements Runnable

{private inti;public voidrun()

{for(;i<100;i++)

{

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

}

}public static voidmain(String args[])

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

{

System.out.println(Thread.currentThread().getName()+""+i);if(i==20)

{

SecondThread st=newSecondThread();new Thread(st,"新线程1").start();new Thread(st,"新线程2").start();

}

}

}

}

SecondThread

方法三、通过Callable和Future创建线程

这个类似Runnable的升级版,注意的是,Callable出来的东西可以带返回值,但是不能直接使用,要用FutureTask包装才有Runnable接口,call的返回值在try中捕获

具体方法,对象.get(),直接在main函数里面写就可以,不用run了。

注意一下(第一次跑的时候意外,main全部在前面执行了,实际上从i到20开新的线程以后他们是交替进行的。)

使用的是Lambda表达式。

Callable和Future都是有import的,并且直接util.*不太好用。。折腾了半天,记得看eclipse的提醒

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

package threadtry;

import java.io.*;

import java.util.*;

import java.util.concurrent.Callable;

import java.util.concurrent.FutureTask;public classThirdThread {public static voidmain(String args[])

{

ThirdThread rt=newThirdThread();

FutureTasktask=new FutureTask((Callable)()->{int i=0;for(;i<100;i++)

{

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

}returni;

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

System.out.println(Thread.currentThread().getName()+""+i);if(i==20)

{new Thread(task,"有返回值的线程").start();

}

}try{

System.out.println("子线程的返回值"+task.get());

}catch(Exception ex)

{

ex.printStackTrace();

}

}

}

ThirdThread

线程的三种创建方式中,继承thread比较基础,但是不能继承其他父类。

线程的生命周期经过:新建->就绪->运行->阻塞->死亡五种状态。

new是新建

start以后进入就绪状态

运行是根据JVM里面的实际调度来确认的

关于线程休眠(比如我现在在i==20要立刻执行子线程),用到sleep函数,但是可能有exception,需要处理,格式如下。Thread.sleep(100),休眠的是现在正在运行的线程,单位是根据编译环境在变的

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

package threadtry;public classFirstThread extends Thread

{private inti;public voidrun()

{for(;i<100;i++)

{

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

}

}public static voidmain(String args[])

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

{

System.out.println(Thread.currentThread().getName()+""+i);if(i==20)

{try{

Thread.sleep(100);

}catch(InterruptedException e)

{System.out.println(e);}newFirstThread().start();newFirstThread().start();

}

}

}

}

sleep函数

在其他线程执行开始以后,他们的地位就和主线程是平等的,并不会因为主线程的结束而结束。判断线程是否死亡(在就绪、运行、阻塞状态认为非死亡)isAlive()函数,死亡以后不能重启的哦

join函数可以保证插入的这个线程都运行结束以后才可以运行调用的线程(注意对其他线程不产生干扰的)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

package threadtry;

import java.util.*;

import java.io.*;public classJoinThread extends Thread

{publicJoinThread(String name)

{

super(name);

}public voidrun()

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

{

System.out.println(getName()+""+i);

}

}public static voidmain(String args[])

{new JoinThread("新线程").start();for(int i=0;i<100;i++)

{if(i==20)

{

JoinThread jt=new JoinThread("被Join的线程");

jt.start();try{

jt.join();

}catch(InterruptedException e)

{

System.out.println(e);

}

}

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

}

}

}

Join

这里面,在i==20的时候是main调用了jt,jt开始运行(main的20已经开始了,但是因为在最后面输出,所以被阻塞了,要jt全完事儿才可以。)中途就是jt和命名为新线程的两个东西争夺内存。

后台线程 Daemon,在前台线程全部死亡以后,后台线程自动死亡(注意一下extends Thread)

8f900a89c6347c561fdf2122f13be562.png

961ddebeb323a10fe0623af514929fc1.png

packagethreadtry;import java.io.*;import java.util.*;public class DaemonThread extendsThread

{public voidrun()

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

{

System.out.println(getName()+""+i);

}

}public static voidmain(String args[])

{

DaemonThread t=newDaemonThread();

t.setDaemon(true);

t.start();for(int i=0;i<10;i++)

{

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

}

}

}

View Code

sleep与yield最大的区别是,yield只会给优先级相同或者更高的线程执行机会,更建议使用sleep

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值