java语言基础(88)——多线程(实现多线程的四种方式)

至于什么是线程,什么是进程,多线程的意义与多进程的意义,不是本文的终点,本文着重记录多线程的实现方式。

方式一:

将类声明为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方式来实现。




猜你喜欢

转载自blog.csdn.net/wang740209668/article/details/77972251