publicclassMyRunnableimplementsRunnable{@Overridepublicvoidrun(){for(int i=0; i<100; i++){System.out.println(Thread.currentThread().getName()+":"+i);}}}publicclassMyRunnableDemo{publicstaticvoidmain(String[] args){//创建MyRunnable类的对象MyRunnable my =newMyRunnable();//创建Thread类的对象,把MyRunnable对象作为构造方法的参数//Thread(Runnable target)// Thread t1 = new Thread(my);// Thread t2 = new Thread(my);//Thread(Runnable target, String name)Thread t1 =newThread(my,"坦克");Thread t2 =newThread(my,"飞机");//启动线程
t1.start();
t2.start();}}
1.6实现多线程方式三: 实现Callable接口【应用】
方法介绍
方法名
说明
V call()
计算结果,如果无法计算结果,则抛出一个异常
FutureTask(Callable callable)
创建一个 FutureTask,一旦运行就执行给定的 Callable
V get()
如有必要,等待计算完成,然后获取其结果
实现步骤
定义一个类MyCallable实现Callable接口
在MyCallable类中重写call()方法
创建MyCallable类的对象
创建Future的实现类FutureTask对象,把MyCallable对象作为构造方法的参数
创建Thread类的对象,把FutureTask对象作为构造方法的参数
启动线程
再调用get方法,就可以获取线程结束之后的结果。
代码演示
publicclassMyCallableimplementsCallable<String>{@OverridepublicStringcall()throwsException{for(int i =0; i <100; i++){System.out.println("跟女孩表白"+ i);}//返回值就表示线程运行完毕之后的结果return"答应";}}publicclassDemo{publicstaticvoidmain(String[] args)throwsExecutionException,InterruptedException{//线程开启之后需要执行里面的call方法MyCallable mc =newMyCallable();//Thread t1 = new Thread(mc);//可以获取线程执行完毕之后的结果.也可以作为参数传递给Thread对象FutureTask<String> ft =newFutureTask<>(mc);//创建线程对象Thread t1 =newThread(ft);String s = ft.get();//开启线程
t1.start();//String s = ft.get();System.out.println(s);}}
三种实现方式的对比
实现Runnable、Callable接口
好处: 扩展性强,实现该接口的同时还可以继承其他的类
缺点: 编程相对复杂,不能直接使用Thread类中的方法
继承Thread类
好处: 编程比较简单,可以直接使用Thread类中的方法
缺点: 可以扩展性较差,不能再继承其他的类
1.7设置和获取线程名称【应用】
方法介绍
方法名
说明
void setName(String name)
将此线程的名称更改为等于参数name
String getName()
返回此线程的名称
Thread currentThread()
返回对当前正在执行的线程对象的引用
代码演示
publicclassMyThreadextendsThread{publicMyThread(){}publicMyThread(String name){super(name);}@Overridepublicvoidrun(){for(int i =0; i <100; i++){System.out.println(getName()+":"+i);}}}publicclassMyThreadDemo{publicstaticvoidmain(String[] args){MyThread my1 =newMyThread();MyThread my2 =newMyThread();//void setName(String name):将此线程的名称更改为等于参数 name
my1.setName("高铁");
my2.setName("飞机");//Thread(String name)MyThread my1 =newMyThread("高铁");MyThread my2 =newMyThread("飞机");
my1.start();
my2.start();//static Thread currentThread() 返回对当前正在执行的线程对象的引用System.out.println(Thread.currentThread().getName());}}
1.8线程休眠【应用】
相关方法
方法名
说明
static void sleep(long millis)
使当前正在执行的线程停留(暂停执行)指定的毫秒数
代码演示
publicclassMyRunnableimplementsRunnable{@Overridepublicvoidrun(){for(int i =0; i <100; i++){try{Thread.sleep(100);}catch(InterruptedException e){
e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"---"+ i);}}}publicclassDemo{publicstaticvoidmain(String[] args)throwsInterruptedException{/*System.out.println("睡觉前");
Thread.sleep(3000);
System.out.println("睡醒了");*/MyRunnable mr =newMyRunnable();Thread t1 =newThread(mr);Thread t2 =newThread(mr);
t1.start();
t2.start();}}
1.9线程优先级【应用】
线程调度
两种调度方式
分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些
Java使用的是抢占式调度模型
随机性假如计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的![外链图片转存失败,源站可能有防盗链机制,建议将图片保存下来直接上传](https://img-home.csdnimg.cn/images/20230724024159.png?origin_url=.%5Cimg%5C05_%E5%A4%9A%E
优先级相关方法
方法名
说明
final int getPriority()
返回此线程的优先级
final void setPriority(int newPriority)
更改此线程的优先级线程默认优先级是5;线程优先级的范围是:1-10
代码演示
publicclassMyCallableimplementsCallable<String>{@OverridepublicStringcall()throwsException{for(int i =0; i <100; i++){System.out.println(Thread.currentThread().getName()+"---"+ i);}return"线程执行完毕了";}}publicclassDemo{publicstaticvoidmain(String[] args){//优先级: 1 - 10 默认值:5MyCallable mc =newMyCallable();FutureTask<String> ft =newFutureTask<>(mc);Thread t1 =newThread(ft);
t1.setName("飞机");
t1.setPriority(10);//System.out.println(t1.getPriority());//5
t1.start();MyCallable mc2 =newMyCallable();FutureTask<String> ft2 =newFutureTask<>(mc2);Thread t2 =newThread(ft2);
t2.setName("坦克");
t2.setPriority(1);//System.out.println(t2.getPriority());//5
t2.start();}}
1.10守护线程【应用】
相关方法
方法名
说明
void setDaemon(boolean on)
将此线程标记为守护线程,当运行的线程都是守护线程时,Java虚拟机将退出
代码演示
publicclassMyThread1extendsThread{@Overridepublicvoidrun(){for(int i =0; i <10; i++){System.out.println(getName()+"---"+ i);}}}publicclassMyThread2extendsThread{@Overridepublicvoidrun(){for(int i =0; i <100; i++){System.out.println(getName()+"---"+ i);}}}publicclassDemo{publicstaticvoidmain(String[] args){MyThread1 t1 =newMyThread1();MyThread2 t2 =newMyThread2();
t1.setName("女神");
t2.setName("备胎");//把第二个线程设置为守护线程//当普通线程执行完之后,那么守护线程也没有继续运行下去的必要了.
t2.setDaemon(true);
t1.start();
t2.start();}}