您当前的位置: 首页 > 学无止境 > 心得笔记 网站首页心得笔记
【第9章:多线程】_认识多线程
发布时间:2020-12-20 12:36:49编辑:雪饮阅读()
多线程的基础使用
class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name=name;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println(name+"运行 i="+i);
}
}
}
public class TestJava{
public static void main(String args[]){
MyThread mt1=new MyThread("线程A");
MyThread mt2=new MyThread("线程B");
mt1.run();
mt2.run();
}
}
D:\>javac TestJava.java
D:\>java TestJava
线程A运行 i=0
线程A运行 i=1
线程A运行 i=2
线程A运行 i=3
线程A运行 i=4
线程A运行 i=5
线程A运行 i=6
线程A运行 i=7
线程A运行 i=8
线程A运行 i=9
线程B运行 i=0
线程B运行 i=1
线程B运行 i=2
线程B运行 i=3
线程B运行 i=4
线程B运行 i=5
线程B运行 i=6
线程B运行 i=7
线程B运行 i=8
线程B运行 i=9
像是这样,多线程基础使用就是直接基础Thread类然后覆写其run方法即可,但是你会发现执行结果并非异步同时的,如果是异步同时运行则执行结果因为每个cpu抢占的时间片的先后顺序不同而会导致运行结果中是线程A、B进行穿插,而不是像现在这样先运行了线程A后运行了线程B。
Thread的start方法
那么正确的线程使用方式应该是调用Thread的start方法,该方法会异步根据cpu时间片抢占的结果来同时运行各个线程。
class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name=name;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println(name+"运行 i="+i);
}
}
}
public class TestJava{
public static void main(String args[]){
MyThread mt1=new MyThread("线程A");
MyThread mt2=new MyThread("线程B");
mt1.start();
mt2.start();
}
}
D:\>javac TestJava.java
D:\>java TestJava
线程A运行 i=0
线程A运行 i=1
线程A运行 i=2
线程A运行 i=3
线程A运行 i=4
线程A运行 i=5
线程A运行 i=6
线程B运行 i=0
线程A运行 i=7
线程A运行 i=8
线程A运行 i=9
线程B运行 i=1
线程B运行 i=2
线程B运行 i=3
线程B运行 i=4
线程B运行 i=5
线程B运行 i=6
线程B运行 i=7
线程B运行 i=8
线程B运行 i=9
像是这样的结果才符合多线程的调用,结果中线程A、B之间穿插执行的。
重复启动相同的线程会抛出异常
class MyThread extends Thread{
private String name;
public MyThread(String name){
this.name=name;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println(name+"运行 i="+i);
}
}
}
public class TestJava{
public static void main(String args[]){
MyThread mt1=new MyThread("线程A");
mt1.start();
mt1.start();
}
}
D:\>javac TestJava.java
D:\>java TestJava
Exception in thread "main" java.lang.IllegalThreadStateException
线程A运行 i=0
at java.lang.Thread.start(Thread.java:595)
at TestJava.main(TestJava.java:16)线程A运行 i=1
线程A运行 i=2
线程A运行 i=3
线程A运行 i=4
线程A运行 i=5
线程A运行 i=6
线程A运行 i=7
线程A运行 i=8
线程A运行 i=9
Runnable接口也可以实现多线程
实现方式就是子类实现run方法,然后通过子类new一个实例,然后将这个实例以形参交给Thread进行构造一个新实例,然后新实例执行start方法即可。
class MyThread implements Runnable{
private String name;
public MyThread(String name){
this.name=name;
}
public void run(){
for(int i=0;i<10;i++){
System.out.println(name+"运行 i="+i);
}
}
}
public class TestJava{
public static void main(String args[]){
MyThread mt1=new MyThread("线程A");
MyThread mt2=new MyThread("线程B");
Thread t1=new Thread(mt1);
Thread t2=new Thread(mt2);
t1.start();
t2.start();
}
}
D:\>javac TestJava.java
D:\>java TestJava
线程A运行 i=0
线程A运行 i=1
线程A运行 i=2
线程B运行 i=0
线程A运行 i=3
线程B运行 i=1
线程A运行 i=4
线程B运行 i=2
线程A运行 i=5
线程B运行 i=3
线程A运行 i=6
线程B运行 i=4
线程A运行 i=7
线程B运行 i=5
线程A运行 i=8
线程B运行 i=6
线程A运行 i=9
线程B运行 i=7
线程B运行 i=8
线程B运行 i=9
Thread与Runnable实现多线程的区别
上面我们通过Thread与Runnable分别实现了多线程,那么这两个之间有什么区别呢?
其实呢Thread类是Runnable接口的一个实现。那么有没有更明显的区别呢?其实Runnable接口这种方式实现多线程可以对资源的共享,而Thread实现的方式则不能达到资源的共享。
先来看看一个经典的卖票实例
Thread的实现方式
class MyThread extends Thread{
private int ticket = 5 ;
private String name;
public MyThread(String name){
this.name=name;
}
public void run(){
for(int i=0;i<100;i++){
if(this.ticket>0){
System.out.println("线程"+this.name+"卖票:ticket = " + ticket--) ;
}
}
}
}
public class TestJava{
public static void main(String args[]){
MyThread mt1=new MyThread("线程A");
MyThread mt2=new MyThread("线程B");
mt1.start();
mt2.start();
}
}
D:\>javac TestJava.java
D:\>java TestJava
线程线程A卖票:ticket = 5
线程线程A卖票:ticket = 4
线程线程A卖票:ticket = 3
线程线程B卖票:ticket = 5
线程线程B卖票:ticket = 4
线程线程B卖票:ticket = 3
线程线程B卖票:ticket = 2
线程线程B卖票:ticket = 1
线程线程A卖票:ticket = 2
线程线程A卖票:ticket = 1
很明显你会发现线程A和线程B各自将总票数独立然后每次各自抢占到cpu时间片之后并没有统一的总票数进行减法操作,而是在自己线程独有的总票数进行减法操作。
Runnable的实现方式
class MyThread implements Runnable{
private int ticket = 5 ;
private String name;
public MyThread(String name){
this.name=name;
}
public void run(){
for(int i=0;i<100;i++){
if(this.ticket>0){
System.out.println("线程"+this.name+"卖票:ticket = " + ticket--) ;
}
}
}
}
public class TestJava{
public static void main(String args[]){
MyThread mt1=new MyThread("线程A");
Thread t1=new Thread(mt1);
Thread t2=new Thread(mt1);
t1.start();
t2.start();
}
}
D:\>javac TestJava.java
D:\>java TestJava
线程线程A卖票:ticket = 5
线程线程A卖票:ticket = 3
线程线程A卖票:ticket = 2
线程线程A卖票:ticket = 1
线程线程A卖票:ticket = 4
这种实现方式真的就是共享了资源
不过我认为Thread实现也是可以的,有些人真的需要好好反思一下了
class MyThread extends Thread{
private int ticket = 5 ;
private String name;
public MyThread(String name){
this.name=name;
}
public void run(){
for(int i=0;i<100;i++){
if(this.ticket>0){
System.out.println("线程"+this.name+"卖票:ticket = " + ticket--) ;
}
}
}
}
public class TestJava{
public static void main(String args[]){
MyThread mt1=new MyThread("线程A");
Thread t1=new Thread(mt1);
Thread t2=new Thread(mt1);
t1.start();
t2.start();
}
}
关键字词:java,多线程