4 formas de realizar la programación de hilos

4 formas de realizar la programación de hilos

1. Heredar hilo

La clase Thread esencialmente implementa una instancia de la interfaz Runnable, que representa una instancia de un hilo.

public class Thread implements Runnable 
@FunctionalInterface //函数式接口,其中包含一个抽象方法run 
public interface Runnable {
    
     
	public abstract void run(); 
}

La única forma de iniciar un hilo es a través del método de instancia start () de la clase Thread. No puedes llamar directamente al método run (). El método start () es un método nativo, que iniciará un nuevo hilo y ejecutará el método run (). El multihilo de esta manera es muy simple. Puede extender Thread directamente a través de su propia clase y anular el método run () para iniciar un nuevo hilo y ejecutar su propio método run () definido.

class LeftThread extends Thread{
    
    
	public void run() {
    
     
		for(int i=0;i<50;i++) {
    
     
			System.out.println("左手一个慢动作..."); 
			try {
    
    //使当前正在执行的线程休眠等待500ms 
				Thread.sleep(500); 
			} catch (InterruptedException e) {
    
     
				e.printStackTrace(); 
			} 
		} 
	} 
}
//在主线程中启动这个线程 
Thread t1=new LeftThread(); 
t1.start();//不能直接调用run方法,否则就是在主线程中单线程执行,不是多线程

Lectura del código fuente:
la clase pública Thead implementa
atributos importantes de la definición de la clase de subproceso Runnable {}

/* what will be run. */ 
private Runnable target;

La implementación de métodos de interfaz, la firma del método no se puede modificar al anular la definición

public void run(){
    
     
	if(target!=null) 
		target.run(); 
}

Implementación de lectura aproximada

public synchronized void start() {
    
     
	if (threadStatus != 0) //当前线程状态检查 
		throw new IllegalThreadStateException(); 
	group.add(this); //将当前线程对象添加到一个线程组中进行管理 
	boolean started = false; //标志值用于判断当前线程是否已经启动 
	try {
    
    
		start0(); 
		started = true; 
	} finally {
    
     
		try {
    
    
			if (!started) {
    
     
				group.threadStartFailed(this); 
			} 
		} catch (Throwable ignore) {
    
     
		} 
	}	 
}
private native void start0();//通过对等类实现启动线程的细节,内部就是自动调用run()方法

Definir clase de hilo

class LeftThread extends Thread{
    
     
	//定义左手线程类,只需要覆盖(重写)定义其中的run()方法,这里实际就是线程的执行线索,执行的程序 
	public void run(){
    
     
		for(int i=0;i<50;i++) 
			System.out.println("左手一个慢动作....") 
	} 
}

Método de llamada

Thread t1=new LeftThread(); 
t1.start();//启动线程必须使用start方法,而不能是调用run方法 
//t1.run();不允许直接调用run方法,因为这种调用方式不是多线程,而是单线程
public class T4 {
    
     
	public static void main(String[] args) {
    
     
		new Thread() {
    
     
			public void run() {
    
     
				System.out.println("匿名类内部输出"+Thread.currentThread().getName()); 
			} 
		}.run();//从语法上来说,可以直接调用run方法,但是运行run方法则不是多线程 
		//.start();输出结果证明不是main线程 
		System.out.println("main方法输出"+Thread.currentThread().getName()); 
	}
}

Si juzga el estado de ejecución del hilo:

最简单的方式是查看线程个数 
// Thread.currentThread()用于获取当前正在运行这个代码的线程对象 
System.out.println(Thread.currentThread()); 
Thread t1 = new LeftThread(); 
// t1.run();在当前主线程中执行t1对象中的run方法 
// t1.start();可以在LeftThread中获取到另外一个线程对象 

public class LeftThread extends Thread {
    
     
	@Override 
	public void run() {
    
    // 这里包含的就是执行线索 
		System.out.println(Thread.currentThread()); 
	} 
}

La mayor limitación es en realidad el sistema de herencia de raíz única de Java, que es básicamente innecesario

2. Implementar la interfaz Runnable

Definición de interfaz

@FunctionalInterface //函数式接口,简化定义方式为lambda表达式 
public interface Runnable{
    
     
	public abstract void run(); 
}

Puede usar una expresión lambda para definir o usar una clase interna anónima para definir

class RightRunnable implements Runnable{
    
     
	public void run(){
    
     
		for(int i=0;i<50;i++) 
			System.out.println(Thread.currentThread().getName()+"说:右手慢动作重播!"); 
	} 
}

Método de inicio:

//启动通过实现Runnable接口定义的线程对象,不能直接使用Runnable r=new RightRunnable(); 
Thread t2=new Thread(new RightRunnable()); 
t2.start();

Usa expresiones lambda

//匿名内部类的写法 
Thread t1 = new Thread(new Runnable() {
    
     
	public void run() {
    
     
		for(int i = 0; i < 20; i++) {
    
     
			System.out.println(Thread.currentThread() + "--" + i); 
		} 
	} 
}); t1.start(); 

//lambda表达式的写法---要求接口必须是函数式接口 
Thread t1 = new Thread(()-> {
    
     
	for (int i = 0; i < 20; i++) {
    
     
		System.out.println(Thread.currentThread() + "--" + i); 
	} 
}); t1.start();
static int sum=0; 
public static void main(String[] args){
    
     
	Thread t1=new Thread(){
    
     
		public void run(){
    
     
			for(int i=0;i<=100;i++) 
				sum+=i; 
		} 
	};
	Thread t2=new Thread(new Runnable(){
    
     
		public void run(){
    
     
			for(int i=1;i<=100;i++) 
				sum+=i; 
		} 
	}); 
	t2.start(); 
	t1.start(); 
	try{
    
    
		Thread.currentThread().sleep(1000); 
	}catch(Exception e){
    
     
		e.printStackTrace(); 
	} 
}

Debido a que la suma del parámetro en el proceso es compartida por todos los subprocesos en el proceso (main \ t1 \ t2), los datos se pueden transferir a través del contenido compartido por los subprocesos, pero debido a operaciones concurrentes, los resultados del cálculo pueden ser incorrectos.

3. Utilice interfaces invocables y futuras para crear subprocesos.

@FuntionalInterface //属于函数式接口,所以可以直接使用lambda表达式进行定义 
public interface Callable<V>{
    
     //<>写法叫做泛型,用于定义返回的数据类型 
	V call()throws Exception; 
}

La interfaz Future se utiliza para el resultado de la ejecución del método de llamada en la interfaz Callable y puede probar la ejecución de Callable

public interface Future<V>{
    
    //用于获取Callable接口中的call方法的执行结果 
	boolean cancel(boolean mayIntersupteIfRunning); 
	boolean isCancelled(); 
	boolean isDone(); 
	V get() throws InterruptedException, ExecutionException; 
	V get(long timeout, TimeUnit unit)throws InterruptedException, ExecutionException; 
}

El sistema proporciona una clase de implementación FutureTask of the Future interfaz

public class FutureTask<V> implements RunnableFuture<V> //这个实现类实现了两个接口Runnable和 Future

Con la clase FutureTask, la implementación invocable se puede encapsular en el objeto FutureTask. Al mismo tiempo, debido a que FutureTask implementa la interfaz Runnable, se puede pasar al objeto Thread como parámetro de constructor de la clase Thread para que el hilo ejecute el lógica en el método de llamada correspondiente.

Callable<Integer> myCallable = new MyCallable(); // 创建MyCallable对象 
FutureTask<Integer> ft = new FutureTask<Integer>(myCallable); //使用FutureTask来包装 MyCallable对象 
Thread thread = new Thread(ft);//FutureTask对象作为Thread对象的target创建新的线程 
thread.start(); //线程进入到就绪状态 
int sum = ft.get(); //取得新创建的新线程中的call()方法返回的结果

Uso:
1. Defina la clase de implementación de la interfaz invocable

public class MyCallable implements Callable<Integer>{
    
     
	int begin=0; 
	int end=0; 
	public MyCallable(int begin, int end){
    
     
		this.begin=begin; 
		this.end=end;
	}
	public Integer call()throws Exception{
    
     
		int res=0; 
		for(int k=begin; k<=end; k++) 
			res+=k; 
		System.out.println(Thread.currentThread()+"---"+res); 
		return res; 
	} 
}

2. Llamar

FutureTask[] arr=new FutureTask[10]; 
for(int i=0;i<10;i++){
    
     
	arr[i]=new FutureTask<>(new MyCallable(i*10+1,(i+1)*10)); 
	Thread t=new Thread(arr[i]); 
	t.start(); 
}
int res=0; 
for(int i=0;i<arr.length;i++) 
	res+=((Integer)arr[i].get()); 
System.out.println("计算结果为:"+res);

Nota: FutureTask implementa las interfaces Future y Runnable, por lo que new Thread (futureTask), cuando se ejecuta el método thread.start (), llamará automáticamente al método de llamada en la implementación de la interfaz Callable. Cuando se llama al método futureTask.get (), se puede obtener el resultado de la ejecución del objeto de subproceso correspondiente. Si el subproceso no regresa, el subproceso actual está bloqueado y esperando

4. Utilice el grupo de subprocesos para crear subprocesos

Modelo de peso mosca

Flyweight Pattern se utiliza principalmente para reducir la cantidad de objetos creados para reducir el uso de memoria y mejorar el rendimiento. Este tipo de patrón de diseño es un patrón estructural, que proporciona una forma de reducir el número de objetos para mejorar la estructura de objeto requerida por la aplicación.

Ventajas: reduce en gran medida la creación de objetos y reduce el uso de la memoria del sistema para mejorar la eficiencia de ejecución del programa.

Desventajas: La complejidad del sistema aumenta, el estado externo y el estado interno deben separarse, y el estado externo tiene una naturaleza inherente y no debería cambiar con el cambio del estado interno, de lo contrario, causará confusión en el sistema. .

No consideres los problemas de los hilos

public interface IShape {
    
     
	void draw(); 
}

public class Circle implements IShape {
    
     
	public void draw() {
    
     
		System.out.println("我画一个圆"); 
	} 
}

Definir la clase de fábrica para proporcionar un método para obtener una instancia.

public class ShapeFactory {
    
     
	private static IShape[] shapes = new IShape[20]; 
	static{
    
     
		for(int i=0;i<shapes.length;i++) 
			shapes[i]=new Circle(); 
	}

	public static IShape getShape() {
    
     
		IShape res = null; 
		for (int i = shapes.length - 1; i >= 0; i--) {
    
     
			res = shapes[i]; 
			if (res != null) {
    
     
				shapes[i]=null; 
				break; 
			} 
		}
		return res; 
	}

	public static void relaseShape(IShape circle) {
    
     
		for (int i = 0; i < shapes.length; i++) {
    
     
			IShape obj = shapes[i]; 
			if (obj == null) 
				shapes[i] = circle; 
		} 
	} 
}

Use ExecutorService, Callable y Future para implementar subprocesos que devuelvan resultados. La implementación específica del grupo de conexiones en realidad depende de ThreadPoolExecutor

//需要计算1+...+10000 
public class T1 {
    
     
	public static void main(String[] args) throws Exception {
    
     
		// 创建一个固定大小的连接池,经常实现使用少量线程以应对波峰请求 
		ExecutorService es = Executors.newFixedThreadPool(3); 
		// 为了使用返回结果所以使用Callable 
		Future[] fs = new Future[10]; 
		for (int i = 0; i < fs.length; i++) {
    
     
			Callable<Integer> caller = new MyCallable(i * 1000 + 1, (i + 1) * 1000); 
			// 使用线程池执行任务并获取Future对象 
			fs[i]=es.submit(caller); 
		}
		int res=0; 
		for(int i=0;i<fs.length;i++){
    
     
			Object obj=fs[i].get(); 
			if(obj!=null && obj instanceof Integer) 
				res+=(Integer)obj; 
		}
		es.shutdown();//关闭线程池 
		System.out.println("Main:"+res); 
	} 
}

class MyCallable implements Callable<Integer> {
    
     
	private int begin; 
	private int end; 
	public MyCallable(int begin, int end) {
    
     
		this.begin = begin; 
		this.end = end; 
	}

	public Integer call() throws Exception {
    
     
		System.out.println(Thread.currentThread()+"---"+begin+".."+end); 
		int res = 0; 
		for (int i = begin; i <= end; i++) 
			res += i; 
		return res; 
	} 
}

Supongo que te gusta

Origin blog.csdn.net/qq_43480434/article/details/113872312
Recomendado
Clasificación