java :多线程实现的三种方式

一、并行、串行、并发

在了解java中多线程的三种实现方式之前,我们首先需要明白并行、串行、并发三个概念。

1.并行:多个CPU同时处理多个任务;

2.串行:单个CPU处理多个任务,当一个任务执行完成之后下一个任务才能够执行;

3.并发:单个CPU处理多个任务,每个任务都会被分一定的时间片,一个任务执行一段时间无论完成与否都要切换另一个任务执行。

在java中多线程其实就是并发的一种模式。

二、java实现多线程的三种方式

我们以买咖啡为例,现在咖啡店只有一个窗口,将每一个人买咖啡的过程视为一个任务。

1.实现Runnable接口

 package  multithreading;  public   class  LRunnableOne {  public   static   void  buyCoffee(String name) {
System.out.println(name
+ "开始买咖啡" );
System.out.println(name
+ "正在买咖啡" );
System.out.println(name
+ "买完了" );
}
public static void main(String[] args) {
Thread t1
= new Thread( new lr("张三" ));
Thread t2
= new Thread( new lr("李四" ));
Thread t3
= new Thread( new lr("王五" ));
System.out.println(
"run方法并不会启动新的线程,只是执行线程中run内的方法,仍然是在主线程上依次上进行" );
t1.run();
t2.run();
t3.run();
System.out.println(
"start方法会启动新的线程,并发执行" );
t1.start();
t2.start();
t3.start();
}
}
class lr implements Runnable{

String name;
public lr(String name) { this .name = name;
}
@Override
public void run() {
LRunnableOne.buyCoffee(name);
}
}

 

 

 这里我们先是直接调用了run方法,又调用了start方法,这样做是为了说明start方法与run方法的不同。start方法是启动就绪的线程,然后调用线程内的run方法;run并不会启动线程,只是执行其中的方法体。start方法只能调用一次,但是run方法可以调用多次。

 

2.继承Thread类

 package  multithreading;  public   class  LThreadOne {  public   static   void  buyCoffee(String name) {
System.out.println(name
+ "开始买咖啡" );
System.out.println(name
+ "正在买咖啡" );
System.out.println(name
+ "买完了" );
}
public static void main(String[] args) {
th th1
= new th("张三" );
th th2
= new th("李四" );
th th3
= new th("王五" );
th1.start();
th2.start();
th3.start();
}
}
class th extends Thread {

String name;
public th(String name) { this .name = name;
}
@Override
public void run() {
LThreadOne.buyCoffee(name);
}
}

3.实现Callable接口

 package  multithreading;  import  java.util.concurrent.Callable;  import  java.util.concurrent.FutureTask;  public   class  LCallable {  public   static   void  buyCoffee(String name) {
System.out.println(name
+ "开始买咖啡" );
System.out.println(name
+ "正在买咖啡" );
System.out.println(name
+ "买完了" );
}
public static void main(String[] args) {
lca l1
= new lca("张三" );
lca l2
= new lca("李四" );
lca l3
= new lca("王五" );
FutureTask futureTask1
= new FutureTask<> (l1);
FutureTask futureTask2
= new FutureTask<> (l2);
FutureTask futureTask3
= new FutureTask<> (l3);
Thread thread1
= new Thread(futureTask1);
Thread thread2
= new Thread(futureTask2);
Thread thread3
= new Thread(futureTask3);
thread1.start();
thread2.start();
thread3.start();
}
}
class lca implements Callable {

String name;
public lca(String name) { this .name = name;
}

@Override
public String call() throws Exception {
LCallable.buyCoffee(name);
return null ;
}
}

 

 

以上就是java中三种实现多线程的方式。但是观察以上结果我们也不难发现一个问题,一个窗口售卖咖啡,应该是一个人买完了另一个人才能开始买。还好这里仅仅是售卖咖啡,如果是银行的存取款,就可能会出现一笔存款被取多次的问题,这就是线程的安全问题。

线程安全问题:当多个线程操作同一个数据时,可能会出现数据的异常。

具体解决线程安全问题就需要用到同步和互斥的概念了。

互斥:一个共享资源,A访问时,其它的都被阻塞(不能访问),当A访问完成时另一个才能访问;

同步:A的结果是B的前提,也就是A、B不能同时运行。

互斥是一种特殊的同步,而同步是更为复杂的互斥。

 

(本文仅作个人学习记录用,如有纰漏敬请指正)

 

标签: Java

添加新评论