沪-飏的gravatar头像
沪-飏 2014-12-09 09:23:18

java多线程编程代码学习实例

java多线程

一、引言

通常,用并发结局的问题大体上可以分为“速度”和“设计可管理性”两种。

  • 速度:多线程机制可以通过 频繁的线程间切换 ,有效的避免“ 阻塞 ”问题;
  • 设计可管理性:也就是改善代码设计,并发编程更符合人的实际逻辑,可以有效的解决 仿真 相关的问题。

二、java线程

1.创建与启动

java中通常有两种方式创建线程:

  • 扩展java.lang.Thread类

      public class taskT extends Thread{
        public void run() {
          System.out.println("正在执行Runnable!");
        }
        public static void main(String[] args) {
          Thread t =new taskT();
          t.start();
        }
      }
  • 实现java.lang.Runnable接口

      public class taskR implements Runnable{
        @Override
        public void run() {
          System.out.println("正在执行Runnable!");
        }
      }
    
      public static void main(String[] args) {
        taskR r = new taskR();
        Thread thread = new Thread(r);
        thread.start();
      }

一旦创建一个新线程并开始执行,即调用start方法时,虚拟机中就又多一个进程,这个进程和原先的进程时并行的。

public class TaskR implements Runnable{
  @Override
  public void run() {
    System.out.println("正在执行线程B!");
    System.out.println("已经执行完线程B!");
  }
}

public class test {
  public static void main(String[] args) {
    System.out.println("正在执行main函数111!");
    TaskR b = new TaskR();
    Thread threadB = new Thread(b);
    System.out.println("准备添加线程B!");
    threadB.start();
    System.out.println("继续执行main函数222!");
//	  for (int i = 0; i < 999999; i++);//延时代码
    System.out.println("正在执行main函数333!");
  }
}

如上程序执行结果输出如下:

正在执行main函数111!
准备添加线程B!
继续执行main函数222!
正在执行main函数333!
正在执行线程B!
已经执行完线程B!

将main函数的注释代码去除注释,增加代码延时,输出如下:

正在执行main函数111!
准备添加线程B!
继续执行main函数222!
正在执行线程B!
已经执行完线程B!
正在执行main函数333!

由上两组对比不难发现,当线程threadB一旦开始执行(执行threadbB.start()),main函数这条线程和线程threadB是并发的。

另外需要注意的是,多线程表面上给人的感觉是多个任务同时进行,实际上并非如此,虚拟机通过频繁的切换进程来给人同时执行的错觉。

2.线程状态的转换

线程的状态是线程控制的基础。线程状态总的可以分为五大类:生、等待、阻塞、睡眠、死。

  • 生:线程已经被new,且未执行;
  • start():线程调用start()方法后即进入等待/可运行状态;
  • yield():此外正在执行的线程也可以通过Thread.yield()方法使当前线程暂停执行,并进入可运行状态,从而让步其他线程,但也可能让步失败,因为该线程可能在进入运行状态后又被再次选中。(注:让步的线程是接着执行线程,还是重新执行,经程序测试是接着执行未执行的代码);
  • 阻塞:线程卡死,或不停执行,跳不出run()方法;
  • sleep():调用Thread.sleep()方法,使线程暂停执行一段时间,即睡眠,可以用来帮助其他进程获得运行机会;
  • 死:线程执行完毕,执行完run()方法。

3.线程的同步与锁

当多个线程同时访问互斥(可交换)数据时,应该同步以保护数据,确保两个线程不会同时更改它。通常用synchronized字段实现,而且只能同步方法或同步代码快。

如果两个线程要执行一个类中的synchronized方法,并且两个线程使用相同的实例来调用方法,那么一次只能有一个线程能够执行方法,另一个需要等待,直到锁被释放。

4.线程的交换

  • notify()
  • notifyAll()
  • wait()

5.线程的调度

  • 休眠:Thread.sleep()
  • 优先级
  • 让步:Thread.yield()
  • 合并:join():join()方法是是在某个线程a中,加入一个线程b,线程b没执行完前,a不得执行。

      public class TaskR implements Runnable{
        @Override
        public void run() {	 
          System.out.println("正在执行线程B!");
          try {
            Thread.sleep(1000);
          } catch (InterruptedException e) {
            e.printStackTrace();
          }
          System.out.println("已经执行完线程B!");
        }
      }
      public class test {
        public static void main(String[] args) throws InterruptedException {
          System.out.println("正在执行main函数!");
          TaskR b = new TaskR();
          Thread threadB = new Thread(b);
          System.out.println("准备添加线程B!");
          threadB.start();
          System.out.println("执行完main");
        }
      }
      public class test2 {
        public static void main(String[] args) throws InterruptedException {
          System.out.println("正在执行main函数!");
          TaskR b = new TaskR();
          Thread threadB = new Thread(b);
          System.out.println("准备添加线程B!");
          threadB.start();
          System.out.println("threadB.join()");
          threadB.join();
          System.out.println("执行完main");
        }
      }

    分别执行test1和test2中的main执行结果如下:

      正在执行main函数!
      准备添加线程B!
      threadB.join()
      执行完main
      正在执行线程B!
      已经执行完线程B!
    

    test2中添加join()方法:

      正在执行main函数!
      准备添加线程B!
      threadB.join()
      正在执行线程B!
      已经执行完线程B!
      执行完main
    

    在threadB中调用sleep是为了让main函数这条线程获得执行机会。有结果,可知当threadB调用join方法后,即使sleep了main函数都不能跑完,说明join方法的作用,即必须threadB执行完才能继续执行main函数。

  • 守护线程

线程池

java.util.concurrent.Executors。 例:

ExecutorService pool = Executors.newFixedThreadPool(2);
Thread t1 = new MyThread(); 
Thread t2 = new MyThread();
Thread t3 = new MyThread();
Thread t4 = new MyThread();
pool.execute(t1);
pool.execute(t2);
pool.execute(t3);
pool.execute(t4);
pool.shutdown();

打赏

最代码最近下载分享源代码列表最近下载
最代码最近浏览分享源代码列表最近浏览
jierffff  LV2 2023年4月13日
浪里格朗  LV4 2023年1月31日
sakura_taiga  LV4 2022年7月3日
MoonSight  LV1 2022年7月1日
bearloadprogress  LV7 2022年5月12日
暂无贡献等级
罐瓶  LV2 2022年2月27日
一道念  LV10 2022年1月29日
为了水掉6位用户名  LV4 2022年1月18日
JiuJiu251 2021年12月15日
暂无贡献等级
顶部 客服 微信二维码 底部
>扫描二维码关注最代码为好友扫描二维码关注最代码为好友