0301 多线程
创建多线程,除了继承Thread类之外,还可以实现Runnable接口
是因为在继承Thread类的时候 我们创建Thread类对象时,既创建线程对象,又开启线程,这样就会导致耦合性太高。在实现Runnable接口时,这个接口的子类对象就只负责开启线程,让Thread类对象只负责创建线程对象,就实现了分工,就降低了耦合性。
代码展示,首先创建一个类实现这个Runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
代码展示,创建测试
public static void main(String[] args) {
//创建线程任务对象
MyRunnable my=new MyRunnable();
//创建线程对象
Thread t=new Thread(my);
Thread t2=new Thread(my);
//开启
t.start();
t2.start();
}
Thread构造方法将线程传进去。
这样就构成了Thread只负责创建线程对象,Runnable只负责创建线程
避免了继承Thread类的单继承的局限性
那我们为了实现多线程,去专门创建一个类,是不是有点浪费
那我们可以使用匿名内部类去实现多线程的操作
代码展示
public static void main(String[] args) {
//继承Thread类的方式
new Thread(){
public void run() {
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}.start();
//实现runnable
Runnable r=new Runnable() {
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
};
//创建线程对象开启线程
new Thread(r).start();
}
上述代码中分别写了Thread类的匿名内部类的创建线程的方式和runnable匿名内部类的创建线程的方式
线程池
创建线程池可以指定创建几条线程,当开启线程的时候会自动给线程池中空闲的线程去执行
使用线程池的方式
(1)runnable接口
Executors类中有一个public static ExecutorService newFixedThreadPool(int nThreads) 方法,返回一个线程池对象
ExecutorService 线程池类中有一个 submit方法获取某一个线程对象
ExecutorService 线程池类中有一个shutdown方法 关闭线程池
代码展示
我们用runnable接口来实现
首先创建一个runnable子类继承这个runnable接口
public class MyRunnable implements Runnable{
@Override
public void run() {
// TODO Auto-generated method stub
for(int i=0;i<100;i++){
System.out.println(Thread.currentThread().getName()+":"+i);
}
}
}
测试
public static void main(String[] args) {
//获取线程池对象
ExecutorService es=Executors.newFixedThreadPool(2);
//描述线程任务
MyRunnable r=new MyRunnable();
//将线程任务对象交给线程池执行
es.submit(r);
es.submit(r);
es.submit(r);
//销毁线程池
es.shutdown();
}
上述代码中 线程池中只有两条线程,但是我们现编提交给线程池三条任务,那就会先执行完前两条线程任务之后再执行最后一条线程
(2)callable接口
该接口可以返回线程任务结束以后所产生的结果,该接口有一个泛型,就是该线程返回值是什么类型 这个泛型就写什么类型
Future<F>接口 用来记录线程任务执行完毕后产生的结果
get() 获取Future对象中封装的数据结果
代码展示,与上述步骤一样,只不过就是多了一个返回值
public class MyCallable implements Callable<String>{
@Override
public String call() throws Exception {
// TODO Auto-generated method stub
return "abc";
}
}
创建测试
public static void main(String[] args) throws InterruptedException, ExecutionException {
//获得线程池对象
ExecutorService es=Executors.newFixedThreadPool(2);
//创建线程任务
MyCallable c=new MyCallable();
//将线程任务交给线程池执行
Future<String> f=es.submit(c);
//获取返回值
String str=f.get();
System.out.println(str);
//销毁线程池
es.shutdown();
}
例举,用线程求1-n的和
创建一个类实现Callable接口
public class GetSum implements Callable<Integer>{
private int number;
public GetSum(int number) {
super();
this.number = number;
}
public GetSum() {
super();
}
public Integer call() throws Exception {
int sum=0;
for(int i=0;i<=number;i++){
sum=sum+i;
}
return sum;
}
}
创建测试类
public static void main(String[] args) throws InterruptedException, ExecutionException {
//获取线程池对象
ExecutorService es=Executors.newFixedThreadPool(2);
//创建线程任务
GetSum g=new GetSum(100);
GetSum gs=new GetSum(200);
//执行
Future<Integer> f1=es.submit(g);
Future<Integer> f2=es.submit(gs);
System.out.println(f1.get());
System.out.println(f2.get());
//关闭
es.shutdown();
}
这样就同时出了1-100的和 and 1-200的和

浙公网安备 33010602011771号