publicclassMyRunnableimplementsRunnable{@Overridepublicvoidrun(){for(int i =0; i <100; i++){System.out.println(Thread.currentThread().getName()+":"+ i);}}}publicclassTest{publicstaticvoidmain(String[] args){//创建MyRunnable类的对象MyRunnable my =newMyRunnable();//创建MyRunnable类的对象Thread t1 =newThread(my);Thread t2 =newThread(my);//启动线程
t1.start();
t2.start();}}
实现多线程方式三: 实现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"答应";}}publicclassTest{publicstaticvoidmain(String[] args)throwsExecutionException,InterruptedException{//线程开启之后需要执行里面的call方法MyCallable mc =newMyCallable();//Thread t1 = new Thread(mc);//可以获取线程执行完毕之后的结果.也可以作为参数传递给Thread对象FutureTask<String> ft =newFutureTask<>(mc);//创建线程对象Thread t1 =newThread(ft);//开启线程
t1.start();//获取return里面的内容String s = ft.get();//输出return里面的内容System.out.println(s);}}
三种实现方式的对比
实现Runnable、Callable接口
好处:扩展性强,实现该接口的同时还可以继承其他类
缺点:编程相对复杂,不能直接使用Thread类中的方法
继承Thread类
好处:编程比较简单,可以直接使用Thread类中的方法
缺点:可以扩展性较差,不能再继承其他类
设置和获取线程名称
方法介绍
方法名
说明
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);}}}publicclassTest{publicstaticvoidmain(String[] args){/*MyThread mt1 = new MyThread();
MyThread mt2 = new MyThread();*///使用setName()方法修改名字/*mt1.setName("张三");
mt2.setName("李斯");*///使用构造方法修改名字MyThread mt1 =newMyThread("王五");MyThread mt2 =newMyThread("赵六");
mt1.start();
mt2.start();System.out.println(Thread.currentThread().getName());}}
线程休眠
相关方法
方法名
说明
static void sleep(long millis)
使当前正在执行的线程停留(暂停执行)指定的毫秒数
publicclassMyRunnableimplementsRunnable{@Overridepublicvoidrun(){for(int i =0; i <100; i++){try{Thread.sleep(100);}catch(InterruptedException e){}System.out.println(Thread.currentThread().getName()+":"+ i);}}}publicclassTest{publicstaticvoidmain(String[] args){MyRunnable mr =newMyRunnable();Thread t1 =newThread(mr);Thread t2 =newThread(mr);
t1.start();
t2.start();}}
线程优先级
线程调度
两种调度方式
分时调度模型:所有线程轮流使用 CPU 的使用权,平均分配每个线程占用 CPU 的时间片
抢占式调度模型:优先让优先级高的线程使用 CPU,如果线程的优先级相同,那么会随机选择一个,优先级高的线程获取的 CPU 时间片相对多一些
Java使用的是抢占式调度模型
随机性 假如计算机只有一个 CPU,那么 CPU 在某一个时刻只能执行一条指令,线程只有得到CPU时间片,也就是使用权,才可以执行指令。所以说多线程程序的执行是有随机性,因为谁抢到CPU的使用权是不一定的