Java多线程的实现

Java多线程的实现:
1.继承Thread类
步骤:
(1)创建一个Thread线程类的子类(子线程),同时重写Thread类的run方法;
(2)创建稿子类的实例对象,并通过调用start()方法启动线程。
示例1:

class MyThread extends Thread {
	private String title;

	public MyThread(String title) {
		this.title = title;
	}

	/*
	 * 这里我们自然会想到产生线程的实例化对象后调用run()方法,实际上我们不能直接去调用run()方法
	 */
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println(this.title + ",i=" + i);
		}
	}
}

public class TestDemo {
	public static void main(String[] args) {
		MyThread myThread1 = new MyThread("Thread1");
		MyThread myThread2 = new MyThread("Thread2");
		MyThread myThread3 = new MyThread("Thread3");
		/*
		 * 这时候只进行了顺序打印,和多线程无关。正确启动多线程能够的方式是调用Thread类中的start()方法 myThread1.run();
		 * myThread2.run(); myThread3.run();
		 */
		myThread1.start();
		myThread2.start();
		myThread3.start();
	}
}

已注释代码部分的顺序执行结果:
在这里插入图片描述
正确的运行结果:
在这里插入图片描述
示例2(示例1中的部分代码片段):

public class TestDemo {
	public static void main(String[] args) {
		MyThread myThread = new MyThread("Thread1");
		myThread.start();
		System.out.println("运行结束!");
	}
}

运行结果:
在这里插入图片描述
运行结果发现MyThread.java类中的run()方法的执行时间相对于“运行结束!”的执行时间晚,因为start()方法执行比较耗时。
耗时原因:
1)通过JVM告诉操作系统创建Thread;
2)操作系统开辟内存并使用Windows SDK中的creatThread()函数创建Thread线程对象;
3)操作系统对Thread对象进行调度,以确定执行时机;
4)Thread在操作系统中被成功执行。

人为改变输出结果可以在调用start()方法后面调用函数sleep();
具体实现:Thread.sleep(200);

示例3:线程随机性的展现

class MyThread extends Thread {
	public void run() {
		for (int i = 0; i < 10; i++) {
			System.out.println("run=" + Thread.currentThread().getName());
		}
	}
}

public class TestDemo {
	public static void main(String[] args) throws InterruptedException {
		MyThread myThread = new MyThread();
		myThread.setName("myThread");
		myThread.start();

		for (int i = 0; i < 10; i++) {
			System.out.println("main=" + Thread.currentThread().getName());
		}
	}
}

运行结果:
在这里插入图片描述
多线程随机输出的原因是CPU将时间片分给不同的线程,线程获得时间片后就执行任务,所以这些线程在交替地执行并输出,导致输出结果呈现乱序的效果。时间片即CPU分配给各个程序的时间。每个线程被分配一个时间片,在当前的时间片内CPU去执行线程中的任务。需要注意的是,CPU在不同的线程上进行切换时需要耗时的,所以并不是线程创建的越多,软件运行效率就越高,相反,线程数过多反而会降低软件的执行效率。
示例4:执行start()的顺序并不代表执行run()的顺序

class MyThread extends Thread {
	private int title;

	public MyThread(int title) {
		this.title = title;
	}

	public void run() {
		System.out.println(title);
	}
}

public class TestDemo {
	public static void main(String[] args) {
		MyThread myThread1 = new MyThread(1);
		MyThread myThread2 = new MyThread(2);
		MyThread myThread3 = new MyThread(3);
		MyThread myThread4 = new MyThread(4);
		MyThread myThread5 = new MyThread(5);
		MyThread myThread6 = new MyThread(6);
		myThread1.start();
		myThread2.start();
		myThread3.start();
		myThread4.start();
		myThread5.start();
		myThread6.start();
	}
}

运行结果:
在这里插入图片描述
2.实现Runnable接口
———通过继承Thread类的方式实现了多线程,但这种方式有一定局限性,因为Java只支持类的单继承,如果某个类已经继承了其他父类,就无法再继承Thread类来实现多线程。在这种情况下,就可以考虑实现Runnable()方法来实现多线程。
步骤:
1)创建一个Runnable接口的实现类,同时重写接口中的run()方法;
2)创建Runnable接口的实现类对象;
3)使用Thread有参构造方法创建线程实例,并将Runnable接口的实现类的实例对象作为参数传入;
4)调用线程实例的start()方法启动线程。

class MyThread implements Runnable {
	private String title;

public MyThread(String title) {
		this.title = title;
	}

public void run() {
		for (int i = 0; i < 5; i++) {
			System.out.println(this.title + ",i=" + i);
		}
	}
}
/*
 * 程序写到这里会发现,此时MyThread类继承的不再是Thread类而实现了Runnable接口,
 * 虽然解决了单继承局限问题,但是没有start方法被继承了。 这时就要关注Thread类提供的构造方法。 public Thread(Runnable
 * target) 作用:可以接收Runnable接口对象
 */
/*
 * 多线程的启动永远都是Thread类的start()方法
 */

public class TestDemo {
	public static void main(String[] args) {
		MyThread myThread1 = new MyThread("thread1");
		MyThread myThread2 = new MyThread("thread2");
		MyThread myThread3 = new MyThread("thread3");
		new Thread(myThread1).start();
		new Thread(myThread2).start();
		new Thread(myThread3).start();
	}
}

运行结果:
在这里插入图片描述
对于此时的Runnable接口对象可以采用匿名内部类或者Lambda表达式来定义

//匿名内部类
public class TestDemo {
	public static void main(String[] args) {
		new Thread(new Runnable() {
			public void run() {
				System.out.println("Hello World");
			}
		}).start();
	}
}

//Lambda表达式
public class TestDemo {
	public static void main(String[] args) {
		Runnable runnable=()->System.out.println("Hello World");
		new Thread(runnable).start();
	}
}

3.线程类的继承结构
在多线程的处理上使用的就是代理设计模式。除了以上的关系之外,实际上在开发之中使用Runnable还有一个特点:使用Runnable实现的多线程的程序类可以更好的描述出程序共享的概念(并不是说Thread不能)
示例1:使用Thread实现数据共享(产生若干线程进行同一数据的处理操作)
此时启动三个线程实现买票处理,结果变成了买各自的票。

class MyThread extends Thread {
	private int ticket = 5;// 一共5张票

	public void run() {
		while (ticket > 0) {
			System.out.println("剩余票数:" + this.ticket--);
		}
	}
}

public class TestDemo {
	public static void main(String[] args) {
		new MyThread().start();
		new MyThread().start();
		new MyThread().start();

	}
}

运行结果:
在这里插入图片描述
示例2:使用Runnnable实现共享

class MyThread implements Runnable {
	private int ticket = 5;// 一共5张票

	public void run() {
		while (ticket > 0) {
			System.out.println("剩余票数:" + this.ticket--);
		}
	}
}

public class TestDemo {
	public static void main(String[] args) {
		MyThread mt = new MyThread();
		new Thread(mt).start();
		new Thread(mt).start();
		new Thread(mt).start();

	}
}

运行结果:
在这里插入图片描述
4.Callable实现多线程
Runnnable中的run()方法没有返回值。它的设计也遵循了主方法的设计原则;线程一开始就不回头。但是很多时间需要一些返回值,例如某些线程执行完成后可能带来一些返回结果,这种情况下就只能利用Callable来实现多线程。

//使用Callable定义线程主体类
import java.util.concurrent.Callable;
import java.util.concurrent.ExecutionException;
import java.util.concurrent.FutureTask;

class MyThread implements Callable<String> {
	private int ticket = 5;// 一共5张票
	public String call() throws Exception {
		while (this.ticket > 0) {
			System.out.println("剩余票数:" + this.ticket--);
		}
		return "票已经售完";
	}
}
//启动并取得线程的结果
public class TestDemo {
	public static void main(String[] args) throws InterruptedException, ExecutionException {
		FutureTask<String> task = new FutureTask<>(new MyThread());
		new Thread(task).start();
		new Thread(task).start();
		System.out.println(task.get());
	}
}
运行结果:
![在这里插入图片描述](https://img-blog.csdnimg.cn/20190902165716591.png)

                  
                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                               
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值