多线程:
指一个应用程序中有多条并发执行的线索,每条线索被称作为一个线程,他们交替执行,彼此间可以进行通信。
线程:
在我们生活中使用的电脑,在电脑中运行的每一个程序其实都是一个进程,一个进程中还可以有多个执行的单元同时运行,这些单元就可以看作程序执行的一条条线索,被称为线程。每一给进程中至少有一个线程在运行。
线程的实现方式:
第一种:通过继承Thread类实现多线程
实例:
public class Example01 {
public static void main(String[] args) {
MyThread myThread = new MyThread();//创建线程MyThread的线程对象
myThread.start();//开启线程
for (int i = 0; i <= 5; i++){
System.out.println("main()方法:" + i + "在运行");
}
}
}
//MyThread继承Thread类
class MyThread extends Thread{
//重写父类的run()方法
@Override
public void run() {
for(int i = 0; i <= 5; i++){
System.out.println("MyThread的run()方法:" + i + "正在运行");
}
}
}
运行结果:
从上面的结果可以看出来,两个方法的输出语句交替执行,这就实现了多线程。单线程和多线程的区别是,单线程是按照循序执行,而多线程可以同时运行,相互不影响。
第二种:通过实现Runnable接口实现多线程
实例:
public class Example02 {
public static void main(String[] args) {
//创建RunnableDemo类的实例对象
RunnableDemo runnableDemo = new RunnableDemo();
//创建线程对象
Thread thread = new Thread(runnableDemo);
//开启线程,执行线程的run()方法
thread.start();
for (int i = 0;i <= 5; i++ ){
System.out.println("mian方法在" + i + "在运行" );
}
}
}
//RunnableDemo类实现Runnable接口
class RunnableDemo implements Runnable{
//当线程调用了start()方法时,该方法就会执行
public void run() {
for (int i = 0;i <= 5; i++ ){
System.out.println("RunnableDemo类的run()方法:" + i + "在运行" );
}
}
}
运行结果:
Java继承中的单一性的局限性,才会有Runnable接口实现多线程。为了克服弊端,Thread类提供了另外一个构造方法Thread(Runnable r)。其中Runnable是一个接口,它只有一个方法run()方法。当通过Thread(Runnable r)构造方法创建线程对象时,我们只需要为该方法传递一个实现了Runnable接口的实例对象,这样创建的线程将会调用实现Runnable接口中的run()方法最为运行代码。而不需要调用Thread类中的run()方法。
第三种:通过实现Callable接口实现多线程
实例:
public class Example03 {
public static void main(String[] args)throws Exception{
MyCallable callable = new MyCallable();//实例化MyCallable类的实例
FutureTask<String> task = new FutureTask<String>(callable);
new Thread(task).start();//启动线程
String s = task.get();//获得返回值
System.out.println(s);//输出结果
}
}
//MyCallable实现Callable接口
class MyCallable implements Callable<String>{
public String call() throws Exception {
for (int i = 0;i <= 5; i++ ){
System.out.println("MyCallable类的call()方法在" + i + "在运行" );
}
return "MyCallable执行完毕";
}
}
Thread类和Runnable接口的区别:
举一个例子比如一个车站有两个售票窗口,同时出售同一车次的车票。通过Thread类和Runnable接口两个例子看一下效果。
例1:
public class Example04 {
public static void main(String[] args) {
//创建一个线程对象
BusTicket busTicket1 = new BusTicket();
//为线程设置一个名称
busTicket1.setName("窗口1");
//开启该线程
busTicket1.start();
BusTicket busTicket2 = new BusTicket();
busTicket2.setName("窗口2");
busTicket2.start();
}
}
class BusTicket extends Thread{
private int ticket = 64;//车票数量
@Override
public void run() {
int a = 0;
while (a <= 64 ){
a++;
if (ticket > 0 ){
//获取当前线程
Thread thread = Thread.currentThread();
//获取线程的名字
String threadName = thread.getName();
System.out.println(threadName + "正在发第" + ticket-- + "张票");
}
}
}
}
运行结果:
从上面的运行结果可以看出,因为车票是不可能一张同时出售两张,很明显这个结果是不正确的。也就是资源不共享。我们只能在程序中创建一个售票对象,开启多个线程同时去执行售票中的售票方法。也就是说多个线程运行同一个售票程序,这就会用到多线程中的Runnable接口。
例2:
public class Example05 {
public static void main(String[] args) {
//创建线程对象
BusTicket2 busTicket = new BusTicket2();
//启动线程并为线程设置名字
new Thread(busTicket,"窗口1").start();
new Thread(busTicket,"窗口2").start();
}
}
class BusTicket2 implements Runnable{
private int ticket = 64;//车票数量
public void run() {
int a = 0;
while (a <= 64 ) {
a++;
if (ticket > 0 ){
//获取当前线程
Thread thread = Thread.currentThread();
//获取线程的名字
String threadName = thread.getName();
System.out.println(threadName + "正在发第" + ticket-- + "张票");
}
}
}
}
实例:
创建一个线程对象,开启两个线程都调用售票方法,这样就确保了多个线程访问的是同一个资源。
加油吧!!!