码迷,mamicode.com
首页 > 编程语言 > 详细

java 多线程

时间:2018-07-14 13:09:45      阅读:160      评论:0      收藏:0      [点我收藏+]

标签:并发   系统时间   tst   常用   需要   基本概念   技术   ++   场景   

虽然在学习的时候学过多线程编程,但是公司的项目一直没有采用多线程编程,自己对于多线程编程的理解已仅仅的是停留在了最初的学习阶段,

因为最近项目中用到了下载功能,采用单线程下载感觉很慢,所以自己就打算在研究一下多线程,以提高下载的速率。

参考文档:https://www.cnblogs.com/wxd0108/p/5479442.html

一、 基本概念

在使用线程之前应该先了解其概念,“什么是线程?”,“有什么用?”,只有带着问题去学习,你才能更快更好的去学会它(“怎么用?”)。

进程:进程是操作系统中运行的一个任务,一个应用程序运行在一个进程中。进程是一块包含了某些资源的内存区域。操作系统利用进程把它的

    工作划分为一些功能单元。进程中所包含的一个或多个执行单元称为线程。

线程:一个线程是进程的一个顺序执行流,一个进程中可以包含多个线程。

并行:多个cpu实例或者多台机器同时执行一段处理逻辑,是真正的同时。

并发:通过cpu调度算法,让用户看上去同时执行,实际上从cpu操作层面不是真正的同时。并发往往在场景中有公用的资源,

     那么针对这个公用的资源往往产生瓶颈,我们会用TPS或者QPS来反应这个系统的处理能力。

线程安全:经常用来描绘一段代码。指在并发的情况之下,该代码经过多线程使用,线程的调度顺序不影响任何结果。这个时候使用多线程,

        我们只需要关注系统的内存,cpu是不是够用即可。反过来,线程不安全就意味着线程的调度顺序会影响最终结果。

同步:这里的同步,可以理解为“协同步调”,Java中的同步指的是通过人为的控制和调度,保证共享资源的多线程访问成为线程安全,来保证结果的准确。

      我们的程序应该在保证结果准确的同时,提高性能,才是优秀的程序。线程安全的优先级高于性能。

线程的使用场合

  a. 线程通常用于在一个程序中需要同时完成多个任务的情况。我们可以将每个任务定义为一个线程,使他们得以一同工作;

  b. 用于在单一线程中可以完成,但是使用多线程可以更快的情况。eg:下载文件。

线程的状态:

  技术分享图片

二、线程的使用

1. 创建线程

创建线程有两种方式
方式一:继承Thread并重写run方法。

  Thread类是线程类,它的每一个实例都表示一个可以并发运行的线程。我们可以通过继承该类并重写run方法来定义一个具体的线程。

重写run方法的目的只要是为了让线程执行我们所需要的逻辑。

class MyThread1 extends Thread{
    public void run(){
        for(int i=0;i<1000;i++){
            System.out.println("你是谁啊?");
        }
    }
}
Thread t1 = new MyThread1();

启动线程要调用start方法,不要直接调用线程的run()方法当线程启动后,run方法会自动被执行。

线程启动后,何时运行,运行多久都听线程调度管理。线程对于线程调度的工作是不可控的。
即:
  线程何时被分配CPU时间不可控,分配多久时间不可控。线程不能主动向线程调度要时间只能被动被分配。
线程调度会尽可能将CPU时间均匀的分配给所有线程,但不保证一个线程一次这样规律的切换。

此种创建线程的方式有两个不足:
  a. 由于需要继承Thread,而java又是单继承原则,这就导致当前类不能在继承其他类,很多时候会在实践开发中出现继承冲突问题。
  b. 由于在线程内部重写run方法定义了当前线程要执行的任务,这就导致了线程与任务有一个强耦合关系,不利于线程重用。

第二种创建线程的方式:单独定义线程任务,实现Runnable接口。
  实现Runnable接口并重写run方法来定义线程体,然后在创建线程的时候将Runnable的实例传入并启动线程。

  

public class ThreadDemo2 {
    public static void main(String[] args) {
        Runnable r1=new MyRunnable1();
        Runnable r2=new MyRunnable2();
        
        Thread t1=new Thread(r1);
        Thread t2=new Thread(r2);
        
        t1.start();
        t2.start();
    }
}
 class MyRunnable1 implements Runnable{
    public void run() {
        for(int i=0;i<1000;i++){
            System.out.println("你最喜欢的人是谁?");
        }
    }
 }
 class MyRunnable2 implements Runnable{
     public void run(){
         for(int i=0;i<1000;i++){
             System.out.println("我最喜欢的人是xxx!");
         }
     }
 }

优点:

  a. 可以将线程与线程中我们所要执行的业务逻辑分离开来,减少耦合;

  b. 解决了java中单继承的问题,因为接口是多继承的。

方式三:使用匿名内部类完成以上两种线程的创建方式。

  使用该方式可以简化编写代码的复杂度,当一个线程仅需要一个实例时,我们可以通过此方式创建。       

//方式一
new Thread(){
    public void run(){
        for(int i=0;i<1000;i++){

            System.out.println("你爱我么?");
        }
    }
}.start();

//方式二
new Thread(new Runnable(){
    public void run(){
        for(int i=0;i<1000;i++){
            System.out.println("我爱你");
        }
    }
}).start();

2. 线程常用api

2.1 线程优先级

 线程优先级有10个等级,分别用数字1-10表示其中1最低,10最高,5为默认值。
 理论上,优先级越高的线程,获取CPU时间片的次数多。

技术分享图片
Thread max=new Thread(){
    public void run(){
        for(int i=0;i<10000;i++){
            System.out.println("max");
        }
    }
};
Thread min=new Thread(){
    public void run(){
        for(int i=0;i<10000;i++){
            System.out.println("min");
        }
    }
};
Thread norm=new Thread(){
    public void run(){
        for(int i=0;i<10000;i++){
            System.out.println("norm");
        }
    }
};
max.setPriority(Thread.MAX_PRIORITY);
min.setPriority(Thread.MIN_PRIORITY);

min.start();
norm.start();
max.start();
View Code

2.2 线程阻塞sleep()

  线程提供了静态方法:static void sleep(long ms),该方法会将调用该方法的线程阻塞指定毫秒,当阻塞超时后,
 线程会自动回到runnable状态等待分配CPU 时间片继续并发运行。

/*
 * 电子表
 * 每秒钟输出一次当前系统时间
 * 格式:HH:mm:ss
 * 例如:09:53:32
 */
SimpleDateFormat sdf=new SimpleDateFormat("HH:mm:ss");
while(true){
    try{
        System.out.println(sdf.format(new Date()));
        Thread.sleep(1000);
    }catch(Exception e){
        e.printStackTrace();
    }
}

 



3.获取线程相关信息的一系列方法

//获取运行当前代码片段的线程
Thread t=Thread.currentThread(); 
//返回该线程的标识符
long id=t.getId();
//返回该线程的名称
String name=t.getName();
//返回该线程的优先级
int priority=t.getPriority();
//测试线程是否处于活动状态
boolean isAlive=t.isAlive();
//测试线程是否为守护线程
boolean isDaemon=t.isDaemon();
//测试线程是否已经中断
boolean isInterrupted=t.isInterrupted();

 

java 多线程

标签:并发   系统时间   tst   常用   需要   基本概念   技术   ++   场景   

原文地址:https://www.cnblogs.com/shiyun32/p/9308957.html

(0)
(0)
   
举报
评论 一句话评论(0
登录后才能评论!
© 2014 mamicode.com 版权所有  联系我们:gaon5@hotmail.com
迷上了代码!