java笔记Java中的多线程

Posted 棉花糖灬

tags:

篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了java笔记Java中的多线程相关的知识,希望对你有一定的参考价值。

多线程

Java 提供了三种创建线程的方法:

  • 通过实现 Runnable 接口
  • 通过继承 Thread 类本身
  • 通过 Callable 和 Future 创建线程

注意: Java中真正能创建新线程的只有Thread类对象

1. 通过实现 Runnable 接口

通过实现Runnable接口来实现多线程的步骤:

  • 写一个实现Runnable接口的实现类RunnableDemo
  • 在RunnableDemo类中实现Runnable接口的run()方法,里面写线程的执行体
  • 创建RunnableDemo的实例R1
  • 将RunnableDemo实例R1放入Thread实例中创建Thread实例t
  • Thread实例t调用start()方法执行线程
class RunnableDemo implements Runnable {
   private Thread t;
   private String threadName;
   
   RunnableDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // 让线程睡眠一会
            Thread.sleep(50);
         }
      }catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         // 参数:Runnable实例、线程名
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}
 
public class TestThread {
 
   public static void main(String args[]) {
      RunnableDemo R1 = new RunnableDemo( "Thread-1");
      R1.start(); // 执行线程
      
      RunnableDemo R2 = new RunnableDemo( "Thread-2");
      R2.start();
   }   
}

也可以通过匿名实现Runnable接口来实现线程:

// 1.匿名实现Runnable接口并重写run方法
Runnable runnable = new Runnable() {
    @Override
    public void run() {

    }
};
// 2.创建线程对象
// 3.将runnable实例放入线程对象中
Thread thread=new Thread(runnable);
// 4.由线程实例控制线程的行为(运行,停止)
thread.start();

2. 通过继承 Thread 类本身

通过继承Thread类来实现多线程的步骤:

  • 写一个继承Thread类的子类ThreadDemo
  • 在ThreadDemo类中重写run()方法,里面写线程的执行体
  • 创建ThreadDemo的实例T1
  • 将ThreadDemo实例T1放入Thread实例中创建Thread实例t
  • Thread实例t调用start()方法执行线程
class ThreadDemo extends Thread {
   private Thread t;
   private String threadName;
   
   ThreadDemo( String name) {
      threadName = name;
      System.out.println("Creating " +  threadName );
   }
   
   public void run() {
      System.out.println("Running " +  threadName );
      try {
         for(int i = 4; i > 0; i--) {
            System.out.println("Thread: " + threadName + ", " + i);
            // 让线程睡眠一会
            Thread.sleep(50);
         }
      }catch (InterruptedException e) {
         System.out.println("Thread " +  threadName + " interrupted.");
      }
      System.out.println("Thread " +  threadName + " exiting.");
   }
   
   public void start () {
      System.out.println("Starting " +  threadName );
      if (t == null) {
         t = new Thread (this, threadName);
         t.start ();
      }
   }
}
 
public class TestThread {
 
   public static void main(String args[]) {
      ThreadDemo T1 = new ThreadDemo( "Thread-1");
      T1.start();
      
      ThreadDemo T2 = new ThreadDemo( "Thread-2");
      T2.start();
   }   
}

与第一种方式非常类似

3. 通过 Callable 和 Future 创建线程

通过Callable和Future创建线程的步骤:

  • 创建一个实现了Callable接口的实现类CallableThreadTest
  • 实现call()方法,在里面写线程的执行体,并且具有返回值
  • 创建CallableThreadTest类的实例ctt
  • 用FutureTask包装该CallableThreadTest类的实例ctt, 该 FutureTask 对象封装了该 Callable 对象的 call() 方法的返回值
  • 使用 FutureTask 对象作为 Thread 对象 t 的 target 创建线程
  • 调用Thread对象 t 的start()方法启动线程
  • 调用 FutureTask 对象的 get() 方法来获得子线程执行结束后的返回值
public class CallableThreadTest implements Callable<Integer> {
    public static void main(String[] args)  
    {  
        CallableThreadTest ctt = new CallableThreadTest();  
        FutureTask<Integer> ft = new FutureTask<>(ctt);  
        for(int i = 0;i < 100;i++)  
        {  
            System.out.println(Thread.currentThread().getName()+" 的循环变量i的值"+i);  
            if(i==20)  
            {  
                Thread t = new Thread(ft,"有返回值的线程");  
                t.start();
            }  
        }  
        try  
        {  
            System.out.println("子线程的返回值:"+ft.get());  
        } catch (InterruptedException e)  
        {  
            e.printStackTrace();  
        } catch (ExecutionException e)  
        {  
            e.printStackTrace();  
        }  
  
    }
    @Override  
    public Integer call() throws Exception  
    {  
        int i = 0;  
        for(;i<100;i++)  
        {  
            System.out.println(Thread.currentThread().getName()+" "+i);  
        }  
        return i;  
    }  
}

4. Thread类的常用方法

(1) 实例方法

  • public void start():使该线程开始执行;Java 虚拟机调用该线程的 run 方法
  • public void run():如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法;否则,该方法不执行任何操作并返回
  • public final void setName(String name):改变线程名称,使之与参数 name 相同
  • public final void setPriority(int priority):更改线程的优先级
  • public final void setDaemon(boolean on):将该线程标记为守护线程或用户线程
  • public final void join(long millisec):等待该线程终止的时间最长为 millis 毫秒
  • public void interrupt():中断线程
  • public final boolean isAlive():测试线程是否处于活动状态

(2) 静态方法

  • public static void yield():暂停当前正在执行的线程对象,并执行其他线程
  • public static void sleep(long millisec):在指定的毫秒数内让当前正在执行的线程休眠(暂停执行),此操作受到系统计时器和调度程序精度和准确性的影响
  • public static boolean holdsLock(Object x):当且仅当当前线程在指定的对象上保持监视器锁时,才返回 true
  • public static Thread currentThread():返回对当前正在执行的线程对象的引用
  • public static void dumpStack():将当前线程的堆栈跟踪打印至标准错误流

5. Future类的常用方法

上面用到的FutureTask是Future子类的实现类。

(1) 实例方法

  • get():若任务结束后返回结果,反之,则会阻塞线程,直到任务执行完毕
  • get(long timeout, TimeUnit unit):最多再多等待给定的时间,就停止线程
  • cancel(boolean mayInterruptIfRunning):用来停止一个任务,如果任务可以停止(通过mayInterruptIfRunning来进行判断),则可以返回true,如果任务已经完成或者已经停止,或者这个任务无法停止,则会返回false
  • isDone():判断当前方法是否完成
  • isCancel():判断当前方法是否取消

以上是关于java笔记Java中的多线程的主要内容,如果未能解决你的问题,请参考以下文章

通俗易懂两种常用的多线程实现方式——Java并发系列学习笔记

Java中的多线程

Java中的多线程

什么是JAVA的多线程?

如何限制Java程序中的多线程?

Java中的多线程 模拟网络抢票代码