至于什么是线程,什么是进程,多线程的意义与多进程的意义,不是本文的终点,本文着重记录多线程的实现方式。
方式一:
将类声明为Thread的子类,该子类应该重写Thread类的run方法。run方法中的代码是被多线程执行的。
实现过程
1 声明Thread子类
2 重写run方法
3 创建子类对象
4 启动线程(调用start方法启动线程,然后由jvm自动调用run方法)
示例代码:
package ThreadDemo;
public class MyThreadOne extends Thread {
public void run(){
for(int i=0;i<200;i++){
System.out.println(i);
}
}
}
package ThreadDemo;
public class ThreadDemo {
public static void main(String[] args) {
MyThreadOne my1 = new MyThreadOne();//创建第一个线程
MyThreadOne my2 = new MyThreadOne();//创建第二个线程
my1.start();//启动线程
my2.start();//启动线程
}
}
运行上述代码后,如果我们看到数字并不是0-199 和 0-199顺序输出的,那么就证明两个线程存在争夺cup执行权的情况,说明我们实现了多线程的效果
设置和获取线程名称:
我们可以通过getName()方法获得线程的名称,并可以通过setName()方法或带参构造来设置线程的名称,以此来让我们区分不同的线程。
那么如何获取非Thread子类的线程名称呢,比如main方法的线程名称。我们可以用如下方法来获取。
Thread.currentThread().getName()
线程调度,获取和设置线程优先级:
线程调度的两种模型
1 分时调度模型,所有线程轮流使用cpu,平均分配每个线程占用cpu的时间片
2 抢占式调度模型,优先让优先级高的线程使用cpu,优先级相同则随机选取,优先级高的线程获取相对较多的cpu时间片。
通过java api文档我们可以知道,线程默认的优先级为5,最高为10,最低为1
getPriority 和 setPriority 分别可以获取和设置线程的优先级
如下:
package ThreadDemo;
public class ThreadDemo {
public static void main(String[] args) {
MyThreadOne my1 = new MyThreadOne();
MyThreadOne my2 = new MyThreadOne();
my1.setPriority(10);
// System.out.println(my1.getPriority());
// System.out.println(my2.getPriority());
my1.start();
my2.start();
}
}
设置优先级后,多次运行,我们会发现优先级高的确实会优先执行。
方式二:
声明类实现runnable接口。
实现过程
1 声明自定义类,并且实现runnable接口
2 重写run方法
3 创建类的对象实例
4 创建Thread实例,把刚才的自定义类的实例作为参数传递
示例代码:
package ThreadDemo;
public class MyThreadTwo implements Runnable{
public void run() {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+ i);
}
}
}
package ThreadDemo;
public class ThreadDemo {
public static void main(String[] args) {
MyThreadTwo mtt = new MyThreadTwo();
Thread t1 = new Thread(mtt);
Thread t2 = new Thread(mtt);
t1.start();
t2.start();
}
}
此方式解决了java单继承的局限性,并且较好的体现了面向对象的思想。把线程代码抽取(分离)出来,更适合多个程序调用。
方式三:
实现callable接口,配合线程池实现多线程,并且此方式还支持泛型返回值。
示例代码:
package ThreadDemo;
import java.util.concurrent.Callable;
public class MyCallable implements Callable<Integer>{
private int num;
public MyCallable(int num){
this.num = num;
}
public Integer call(){
int sum = 0;
for(int x=0;x<=num;x++){
sum += x;
}
return sum;
}
}
package ThreadDemo;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;
import java.util.concurrent.Future;
public class ThreadPoolDemo {
public static void main(String[] args) throws InterruptedException, ExecutionException {
// 创建线程池
ExecutorService es = Executors.newFixedThreadPool(2);
// 执行Runnable 或 Callable 代表的线程
Future<Integer> f1 = es.submit(new MyCallable(100));
Future<Integer> f2 = es.submit(new MyCallable(200));
//得到返回值
Integer i1 = f1.get();
Integer i2 = f2.get();
System.out.println(i1);
System.out.println(i2);
es.shutdown();
}
}
方式四:
匿名内部类方式
new Thread(){
public void run(){
// ....
}
}.start();
匿名内部类还可以用 Runable方式来实现。