线程及线程池

多线程

Java多线程的使用场景

Java多线程一般在处理大量重复工作,并且这些重复工作相互之间没有关系,比如要处理一万个URL,如果用单线程,就只能重复一万次,但如果使用多线程,将这些URL分割成50份,每个线程就只需要处理200条就行了,这样就大大减少了处理时间;


实现多线程

实现多线程的方法有两种;第一类就是继承Thread类,实现它的 run() 方法:

public class MyTherd extends Thread{
    @Override
  public void run() {
        Systemout();
  SYtemoutname();
  }
    private void Systemout(){
        System.out.print(Thread.currentThread().getName());
  }
    private void SYtemoutname(){
        System.out.println("----will");
  }
}

main方法中调用时是这样的:


//直接新new 一个Thread就可以
Thread mythread=new MyTherd(); mythread.start();

或者:

Thread thread1=new Thread(){
    @Override
  public void run() {
        System.out.println("thread1");
  }
}; 
thread1.start();

第二中是实现Runnable接口,实现它的 run() 方法;

public class MyTherd implements Runnable {
    @Override
  public void run() {
        Systemout();
  SYtemoutname();
  }
    private void Systemout(){
        System.out.print(Thread.currentThread().getName());
  }
    private void SYtemoutname(){
        System.out.println("----will");
  }
}

在main方法中调用的代码是这样的:

/*
*new一个实现Runnable接口的线程类,并传入到Thread中去;
*/
Thread my=new Thread(new MyTherd()); my.start();

或者也可以这样:

Runnable myrun=new Runnable() {
    @Override
  public void run() {
        System.out.println("===will");
  }
}; 
Thread myThread =new Thread( myrun); myThread.start();

在Java中,每个线程都有一块工作区间,其中存放着被所有线程共享的主内存中的变量的值的拷贝。当线程执行时,他在自己的工作内存中操作这些变量。

一个变量是Java程序可以存取的一个地址,它不仅包括基本变量,引用类型变量,而且包括数组类型变量。保存在主内存的标本量可以被所有县城共享,但是一个县城存取另一个县城的参数或者局部变量是不可能的,所以开发人员不必担心局部变量的线程安全问题。

volatile变量 多线程之间可见

由于每个线程都有自己的工作内存区,因此当一个线程改变自己的工作内存中的数据时,对其他线程来说是不可见的。为此,可以使用volatile关键字迫使所有线程均读写内存中的变量,从而使得volatile变量多线程间可见。

volatile int a;
  • 同步关键字synchronized
    synchronized关键字可修饰方法、代码块、和对象;用于添加线程锁;
    • 修饰方法:
public synchronized void synmethod(){
//方法体
}
  • 修饰代码块:
public Object synMethod(Object object){
  synchronized(object) {
  //一次只能有一个线程进入
  }
}
  • 如果synchronized后面括号里是一个对象,此时线程获得的是对象锁,例如:
public classMyThread implements Runnable{
  public static void main(String[] arg){
     MyThread mt=new MyThread();
     Thread t1=newThread(mt,"t1");
     Thread t2=newThread(mt,"t2");
     Thread t3=newThread(mt,"t3");
     t1.start();
     t2.start();
     t3.start();
  }
  public void run(){
    synchronized(this){
      System.out.print(Thread.currentThread().getName());
    }
  }
}

线程池的使用场景

假设一个服务器完成一项任务所需的时间为: T1创建线程时间,T2在县城中执行任务的时间,T3销毁线程时间;
如果:T1+T3远大于T2;则可采用线程池,以提高服务器性能能;
例如服务器要执行10000个请求,并且 每个请求需要一个线程独立完成。在线程池中线程数一般是固定的,所以产生线程总数一般不会超过线程池中线程的数目,而如果不使用线程池来处理这些请求,则线程总数为10000。这样对内存的消耗是非常大的,并且在创建销毁线程上所浪费的时间也是非常大的 。而一般线程池的线程数是远远小于10000的,所以利用线程池的服务器程序不会为了创建10000个线程,而在处理请求是浪费时间,从而提高效率。

使用流程

线程池的使用流程如下:

  1. 创建线程池
    创建线程池时,通过配置线程池的参数,从而实现自己所需的线程池;
  2. 向线程池提交任务:execute()或submit();
  3. 关闭线程池shutdown()

常见的4类功能线程池

根据参数的不同配置,Java中最常见的线程池有4类:
- 定长线程池(FixedThreadPool)
- 定时线程池(ScheduledThreadPool)
- 可缓存线程池(CachedThreadPoole)
- 单线程化线程池(SingleThread)

定长线程池(FixedThreadPool)

定长线程池创建后只有核心线程并且不会被回收、线程数量固定、任务队列无大小限制(超出长度的线程会在任务队列汇总等待)

ExecutorService pool = Executors.newFixedThreadPool(5); for (int i = anInt; i < 8; i++) {
    Runnable myTherd = new MyTherd();
  Thread thread1=new Thread(new MyTherd());
  Thread thread2=new Thread(new MyTherd());
  Runnable runnable1=new MyTherd();
  pool.submit(thread1);
  pool.execute(runnable1);
  pool.execute(thread2);
  pool.execute(myTherd);
  pool.submit(thread1); 
  pool.shutdown();//关闭线程
}

定时线程池(ScheduledThreadPool)

定时线程池的核心线程数量是固定的,非核心线程数量无限制(闲置时马上收回)具有执行定时、周期性任务的优势:

ScheduledExecutorService shedulPool=Executors.newScheduledThreadPool(5);
Runnable myTherd = new MyTherd(); Thread thread1=new Thread(new MyTherd()); 
//延迟一秒后执行任务
shedulPool.schedule(myTherd,1,TimeUnit.SECONDS); 
//延迟10毫秒后每隔100毫秒执行任务
shedulPool.scheduleAtFixedRate(thread1,10,100,TimeUnit.MILLISECONDS);
  shedulPool.shutdown();//关闭线程

可缓存线程池(CachedThreadPool)

可缓存线程池,只有非核心线程、线程数量不定(可无限大)、任何线程任务到来都会立刻执行,不需要等待;可用于执行大量、耗时少的线程任务:

ExecutorService cachedPool=Executors.newCachedThreadPool();
 Thread thread2=new Thread(new MyTherd()); 
 cachedPool.execute(thread2); 
 cachedPool.shutdown();

单线程化线程池(SingleThreadExecutor)

顾名思义,只有一个核心线程,即所有的任务按照指定顺序在一个线程中执行,不需要处理线程同步的问题;
适宜在没有并发但可能引起IO阻塞性及影响UI线程相应的操作,人事局库操纵,文件操作等;

ExecutorService singPool=Executors.newSingleThreadExecutor();

Thread thread2=new Thread(new MyTherd()); 
  singPool.execute(thread2); 
  singPool.shutdown();
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值