【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方法
public static void myRunable() {
        Runnable runnable = new Runnable() {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "  " + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Thread thread1 = new Thread(runnable, "Thread1");
        Thread thread2 = new Thread(runnable, "Thread2");
        thread1.start();
        thread2.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();
   }   
}

与第一种方式非常类似,也可通过匿名内部类来实现:

    public static void myThread() {
        Thread thread1 = new Thread("Thread1") {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "  " + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        Thread thread2 = new Thread("Thread2") {
            @Override
            public void run() {
                for (int i = 0; i < 5; i++) {
                    System.out.println(Thread.currentThread().getName() + "  " + i);
                    try {
                        Thread.sleep(1000);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            }
        };

        thread1.start();
        thread2.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;  
    }  
}

也可以通过匿名内部类来实现:

public static void myCallable() {
        Callable<String> callable = new Callable<String>() {
            @Override
            public String call() throws Exception {
                System.out.println(Thread.currentThread().getName());
                Thread.sleep(1000);
                return Thread.currentThread().getName();
            }
        };

        FutureTask<String> futureTask = new FutureTask<>(callable);

        // 多个Thread使用同一个FutureTask效果和一个Thread一样
        new Thread(futureTask, "Thread").start();

        try {
            System.out.println("线程返回值:" + futureTask.get());
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

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():判断当前方法是否取消
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值