Java多线程理解

Java实现多线程的两种方式分别是继承Thread类和实现Runnable接口。


代码示例:

class MyThread extends Thread{
 private String name;
 
 public MyThread(String name){
  this.name = name;
 }
 
 @Override 
  public void run(){
  for(int i=0;i<7;i++){
   System.out.println("线程开始:"+this.name+"次数"+i);
  }
 }
}
class MyRun implements Runnable{
 @Override
 public void run(){
  for(int i=0;i<7;i++){
   System.out.println("线程开始:"+Thread.currentThread().getName()+"次数"+i);
  }
 }
}
public class A{

 public static void main(String [] args){
 
  MyThread myThread = new MyThread("myThread");
  myThread.start();
 
  MyRun myRun = new MyRun();
  Thread run1 = new Thread(myRun, "myRun");
  run1.start();
 }
}
运行结果:
技术分享


关键点1:启动线程使用start()方法,使用run()方法并不会启动新线程。

public class A{

 public static void main(String [] args){
 
  MyThread myThread1 = new MyThread();
  myThread1.run();
 
  MyThread myThread2 = new MyThread();
  myThread2.run();
 }
} 
class MyThread extends Thread{
 public void run(){
  for(int i=0;i<7;i++){
   System.out.println("线程:"+Thread.currentThread().getName()+"次数"+i);
  }
 }
}

技术分享

start() : 通过调用start0()启动一个新线程,新线程会执行相应的run()方法。start()不能被重复调用。

run(): run()和普通的成员方法一样可重复调用。单独调用run()会在当前线程中执行run(),并不会启动新线程!


相关源码:

public synchronized void start() {
        if (threadStatus != 0)  //start()方法不能被重复调用,否则会抛出异常
            throw new IllegalThreadStateException();
        /* Notify the group that this thread is about to be started
         * so that it can be added to the group's list of threads
         * and the group's unstarted count can be decremented. */
        group.add(this);  //加入到线程组中
        boolean started = false;
        try {
            start0();
            started = true;
        } finally {
            try {
                if (!started) {
                    group.threadStartFailed(this);
                }
            } catch (Throwable ignore) {
                /* do nothing. If start0 threw a Throwable then
                  it will be passed up the call stack */
            }
        }
    }
}
private native void start0();

@Override
public void run() { 
        if (target != null) {   //target是当前的Runnable对象
            target.run();
        }
    }

关键点2:Thread实现多线程与Runnable实现多线程的区别.

1、由于Java使用单继承,多接口实现原则,所以通过Runnable接口实现多线程更具灵活性;
2、Runnable对象可以被多个线程共享,适合于多个线程处理同一资源的情况。(不准确)

卖票问题:

1:Thread

class MyThread extends Thread{
 private int tickets =5;  
 @Override  
    public void run() {  
  while (tickets>0) {  
            tickets--;
            System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余票数:"+tickets);  
       }
    }
}
public static void main(String [] args){
 
  MyThread myThread1 = new MyThread();
  myThread1.start();
 
  MyThread myThread2 = new MyThread();
  myThread2.start();
 }
技术分享

MyThread myThread1 = new MyThread();MyThread myThread2 = new MyThread();
因为每次都创建了新的MyThread对象,所以最后结果是卖了10张票;

2:Runnable
class MyThread extends Thread{
 private int tickets =5;  
 @Override  
    public void run() {  
  while (tickets>0) {  
            tickets--;
            System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余票数:"+tickets);  
       }
    }
}
public static void main(String [] args){
 
  MyRunnable r = new MyRunnable();              
     Thread t1 = new Thread(r);  
     Thread t2 = new Thread(r);  
       
     t1.start();
     t2.start();  
 }
技术分享
MyRunnable对象只有一个,多线程共享同一对象,所以卖票结果好像是正确的。


关键点3:通过实现Runnable接口共享资源。

class MyRunnable implements Runnable{  
 
 private int tickets =10;  
    @Override  
    public void run() {  
     while (tickets>0) {  
             try {  
                Thread.sleep(100);  
             } catch (InterruptedException e) {  
                 e.printStackTrace();  
             }  
             tickets--;
             System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余票数:"+tickets);  
        }  
     
    }  
} 
技术分享
显然最后剩余票数-1和-2是不正确的,所以仅仅实现Runnable接口是无法进行资源共享的,如果需要共享还是需要加入synchronized关键字。

class MyRunnable implements Runnable{  
 
 private int tickets =10;  
    @Override  
    public void run() {  
     synchronized(this){
      while (tickets>0) {  
                tickets--;
                System.out.println(Thread.currentThread().getName()+"卖了一张票,剩余票数:"+tickets);  
           }
     }
    }
}  
技术分享

郑重声明:本站内容如果来自互联网及其他传播媒体,其版权均属原媒体及文章作者所有。转载目的在于传递更多信息及用于网络分享,并不代表本站赞同其观点和对其真实性负责,也不构成任何其他建议。