java中的进程,线程,线程池总结

1、线程与进程

进程

狭义上讲:正在执行的程序,由线程组成,可包含多个线程在运行。

广义上讲:进程是一个具有一定独立功能的程序有关于某个数据集合的一次运行的活动。它可以申请或者拥有系统资源,是一个动态的概念。

进程的概念主要两点:1.进程是一个实体,每一个进程都有自己的地址空间,一般情况下包括文本区域,数据区和堆栈。

线程

为进程中执行的程序片段。

一个线程由线程ID,当前指令针,寄存器和堆栈组成,另外线程是进程的实体,是被系统独立调试的分派的基本单元。

线程是程序中一个单一的顺序控制流程。进程内一个相对独立的、可调度的执行单元,是系统独立调度和分派CPU的基本单位指运行中的程序的调度单位。在单个程序中同时运行多个线程完成不同的工作,称为多线程。


2、线程启动的两种方法;为什么会有这两种方法。

线程中有两种启动方法:

(1)一种是继承Thread类,重写run方法

(2) 另一种是实现Runnable接口,实现run方法。

由于java是单继承的,继承一个类后不能继承其他类。用实现runnable接口启动线程,弥补了java单继承。


3、线程的状态(线程的生命周期)

(1)  创建 : 创建线程也就是new线程;
(2)就绪:调用了start()方法,等待cpu调度;
(3)运行:执行了run()方法;
(4)  阻塞:也就当前线程处于是停止状态,cpu调用其他线程执行。
(5)  消亡:线程销毁。在线程里面的代码执行完毕后,线程自动销毁。

4、线程启动是调用start()方法,为什么不是run()方法

线程的启动是通过调用start()方法的。如果直接调调用线程调用了run()方法,那将与调用普通方法没有区别。

java就把run()方法当成一个普通方法执行,先执行完这个方法再去执行其他的。只有调用一start()方法,才能开启线程。

比如在android中创建一个dialog或者toast,如果没有调用show()方法,这个弹窗也不会显示。


5、线程的常用方法;线程的常用方法基本上都在Thread中

     (1) 得到当前线程名称:Thread.currentThread().getName()
     (2) 取得当前线程对象:currentThread();
     (3) 线程是否执行:isAlive()
     (4) 线程的强行运行:join();
     (5) 线程休眠:sleep();

6、线程的优先级

(1) min_priority: 1

(2) max_priority; 10

(3) norm_priority; 5

在不指定线程优先级的时候,默认优先级为5;

线程的优先级是有可能影响线程的执行顺序,而不是一定按照优先级执行。多线程的执行其实是线程的交换执行

我们提高线程的优先级只是提高了线程执行的概率。比如两个线程的执行的概率都是50%,提高了一个线程概率为60%,另一个则为40%,

但是最终执行的哪个还是靠运气的。比如执行了10次都有可以60%的一次都没执行。


7、线程同步 理解synchronized()关键字

   用来给对象,方法,或者代码加锁,当它锁定一个方法或者代码块的时候,同一个时间只能有一个线程执行这段代码。通常用于多个线程访问一个对象的时候使用。它确保了其他线程必须等待当前线程执行完毕后

才能执行这个代码块或者方法。


8、多线程下载一定能提高下载速度吗

多线程只有在多处理器系统(比如多核、smp等)上才有可能提高执行速率。在多处理系统上,将要执行的任务分割成多个可并行执行线程,就可以提高执行速率。但是如果任务本身不可并行,比如就是一个有限状态自动机的程序,那就没办法用到多处理机,也不能提高速率。上面说的是并行,不是并发。单处理器上多线程只能并发执行而不是并行,多线程并不能提高纯计算程序的速率。但是对于一般程序中都有i/o操作等,可以将io操作放到一个线程中执行,从而可以在io同时进行其他操作不比等待io完成,这样可以提高速率。不宜创建过多线程,因为线程context switch造成很大的cpu负荷,并且线程占用内存资源。现在的网络服务器为了支持大量并发多不是靠多线程或多进程,而采用其他的技术如异步i/o

比如手机是8核的,此时就可以适当的多开线程,去处理下载任务,这样可以利用闲置的CPU。

但对于单核的手机或者其他单核系统呢?

有可能会,也有可能反而降低速度。降低速度的原因是一个CPU,去执行多个线程,在线程间来回不断的切换,反而降低性能。但是,很多情况下(多线程),比如A线程正在下载,B准备下载,这样提高下载的并行,从而也减小下载的时间。

9、线程池

(1)线程池的原因
          对于java来说频繁的创建和销毁对象是比较耗费内存资源的,每次创建一个线程也是一个对象,因此就产生了线程池。
(2)应用情况:需要大量的线程来完成的工作,并且每个工作需要的时间比较短。
(3)线程池中内部工作:
  • 可以规定线程池中线程的数量(也就是最多创建线程的数量),当一个线程执行完一个任务的时候,会接着执行另一个任务,如果这个线程发生异常,则由另一个线程池中的线程来代替
  • 如果任务数量多于线程数量,则没有完成的任务处于等待阶段

创建线程池的几种方法

在java5以后,新增了一个Executors工厂类来创建线程池,在java5在以前都是通过自己实现创建线程池。

在Executors中提供了以下几个静态方法来创建线程池。

  • (1)newCachedThreadPoole() 创建一个具有缓存功能的线程池。
public static ExecutorService newCachedThreadPool()
  • (2)newFixedThradExecutor(int Threads) 创建一个具有固定线程数量的线程池。
public static ExecutorService newFixedThreadPool(int nThreads,ThreadFactory threadFactory)
  • (3)newSingleThreadPool()创建一个只有一个线程的线程池。
public static ExecutorService newSingleThreadExecutor()
  • (4)newScheduledThreadPool()创建具有指定线程数量的线程池,这个线程池中的线程可以指定延迟时间来执行。
public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize)

创建线程池的步骤

  1. 调用Executors类的静态方法创建一个ExecutorService对象,得到一个线程池。
  2. 创建Runnbaler的实现类
  3. 通过submit()方法向线程池提交runnbale线程
  4. 通过shutdown()方法关闭线程池


代码:

1、线程的两种开启方式:

使用继承Thread

public class MyThread extends Thread {
    private String name;

    public MyThread(String name) {
        this.name = name;
    }

    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 100; i++) {
            System.out.println(name+"-----" + i);
        }
        super.run();
    }
}

使用实现runnable接口:

public class MyRunnable implements Runnable{
    private String name;
    public MyRunnable (String name){
        this.name=name;
    }
    public void run() {
        // TODO Auto-generated method stub
        for(int i=0;i<100;i++){
        //得到当前线程的名称;    System.out.println(Thread.currentThread().getName()+"---"+i);
        }
    }

}

在主函数中的两种调用方式:

public static void main(String[] args) {
        // TODO Auto-generated method stub
        //使用继承Thread类创建线程
        // MyThread t1=new MyThread("thread-A");
        // MyThread t2=new MyThread("thread-B");
        // t1.start();
        // t2.start();
        //使用runnable创建线程
        MyRunnable r1 = new MyRunnable("runnable-A");
        MyRunnable r2 = new MyRunnable("runnable-B");
        Thread t1 = new Thread(r1);
        Thread t2 = new Thread(r2);
        t1.start();
        t2.start();

    }


还是对于买票的问题,假如3个窗口买10张票:

package com.threadTest;

public class ThreadTest2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
         MyRunnable2 r2=new MyRunnable2();
         //new 三个线程,相当于三个窗口买票;
         Thread t1=new Thread(r2);
         Thread t2=new Thread(r2);
         Thread t3=new Thread(r2);
         t1.start();
         t2.start();
         t3.start();
    }

}

class MyRunnable2 implements Runnable {
    private int ticket=10;

    public void run() {
        // TODO Auto-generated method stub
        for(int i=0;i<10;i++){
            if(ticket>0){
                try {
                    Thread.sleep(500);
                } catch (InterruptedException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }
                System.out.println("车票"+ticket--);
            }
        }
    }

}

运行结果:出现0,负数。

加上同步锁之后代码:

public class ThreadTest2 {

    public static void main(String[] args) {
        // TODO Auto-generated method stub
        MyRunnable2 r2 = new MyRunnable2();
        // 相当于三个窗口买票;
        Thread t1 = new Thread(r2);
        Thread t2 = new Thread(r2);
        Thread t3 = new Thread(r2);
        t1.start();
        t2.start();
        t3.start();
    }

}

class MyRunnable2 implements Runnable {
    private int ticket = 10;

    public void run() {
        // TODO Auto-generated method stub
        for (int i = 0; i < 10; i++) {
            synchronized (this) {
                if (ticket > 0) {
                    try {
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        // TODO Auto-generated catch block
                        e.printStackTrace();
                    }
                    System.out.println("车票" + ticket--);
                }
            }

        }
    }

}

这样运行后不会再出现负数和0;



创建线程池demo

package com.thrad.demo;

import java.util.concurrent.ExecutorService;
import java.util.concurrent.Executors;

public class ThradTest {
    public static void main(String[] args) {
        //创建一个具有固定线程数量为3的线程池;
        ExecutorService fixedThreadPool = Executors.newFixedThreadPool(3);
        for (int i = 0; i < 100; i++) {
            final int index = i;
            fixedThreadPool.execute(new Runnable() {
                public void run() {
                    try {
                        System.out.println(Thread.currentThread().getName()+"执行的"+index);
                        Thread.sleep(500);
                    } catch (InterruptedException e) {
                        e.printStackTrace();
                    }
                }
            });
        }
    }
}

运行结果:在pool1的线程池中只有三个线程执行新的任务。

时间: 2024-10-05 16:04:09

java中的进程,线程,线程池总结的相关文章

Java中的进程和线程

 Java中的进程与线程 一:进程与线程 概述:几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程:进程是指处于运行过程中的程序,并且具有一定的独立功能.进程是系统进行资源分配和调度的一个单位.当程序进入内存运行时,即为进程. 进程的三个特点: 1:独立性:进程是系统中独立存在的实体,它可以独立拥有资源,每一个进程都有自己独立的地址空间,没有进程本身的运行,用户进程不可以直接访问

Java中的进程与线程(总结篇)

详细文档: Java中的进程与线程.rar 474KB 1/7/2017 6:21:15 PM 概述: 几乎任何的操作系统都支持运行多个任务,通常一个任务就是一个程序,而一个程序就是一个进程.当一个进程运行时,内部可能包括多个顺序执行流,每个顺序执行流就是一个线程. 进程与线程: 进程是指处于运行过程中的程序,并且具有一定的独立功能.进程是系统进行资源分配和调度的一个单位.当程序进入内存运行时,即为线程. 进程拥有以下三个特点: 1:独立性:进程是系统中独立存在的实体,它可以独立拥有资源,每一个

Java中的进程与线程

Java中的进程与线程:http://www.ibm.com/developerworks/cn/java/j-lo-processthread/ Java中的进程与线程

java中的进程与线程及java对象的内存结构【转】

原文地址:http://rainforc.iteye.com/blog/2039501 1.实现线程的三种方式: 使用内核线程实现 内核线程(Kernel Thread, KLT)就是直接由操作系统内核支持的线程,这种线程由内核来完成线程切换,内核通过操作调度器对线程进行调度,并负责将线程的任务映射到各个处理器上.程序一般不会直接去使用内核线程,而是去使用内核线程的一种高级接口——轻量级进程(Light Weight Process,LWP),轻量级进程就是我们通常意义上所讲的线程,由于每个轻量

Python 中的进程、线程、协程、同步、异步、回调

进程和线程究竟是什么东西?传统网络服务模型是如何工作的?协程和线程的关系和区别有哪些?IO过程在什么时间发生? 在刚刚结束的 PyCon2014 上海站,来自七牛云存储的 Python 高级工程师许智翔带来了关于 Python 的分享<Python中的进程.线程.协程.同步.异步.回调>. 一.上下文切换技术 简述 在进一步之前,让我们先回顾一下各种上下文切换技术. 不过首先说明一点术语.当我们说"上下文"的时候,指的是程序在执行中的一个状态.通常我们会用调用栈来表示这个状

我对java中任务取消和线程中断的一点儿理解

在JDK中任务就是一个Runnable或Callable对象,线程是一个Thread对象,任务是运行在某个线程中的.我们知道,让线程死亡的方式有2种:正常完成和未捕获的异常.如果想让任务结束,也只有这2种方式. java中虽然提供了抢占式中断Thread.stop(),但这是很不安全的,JDK早已经将其标记成过时的了.在java中如果想取消一个任务,只能使用中断,中断是一种协作机制.也就是说,如果A线程想中断B线程,那么其实是A向B发送了一个中断请求,至于B到底会不会停止执行,取决于B的实现.如

python中的进程、线程(threading、multiprocessing、Queue、subprocess)

Python中的进程与线程 学习知识,我们不但要知其然,还是知其所以然.你做到了你就比别人NB. 我们先了解一下什么是进程和线程. 进程与线程的历史 我们都知道计算机是由硬件和软件组成的.硬件中的CPU是计算机的核心,它承担计算机的所有任务. 操作系统是运行在硬件之上的软件,是计算机的管理者,它负责资源的管理和分配.任务的调度. 程序是运行在系统上的具有某种功能的软件,比如说浏览器,音乐播放器等. 每次执行程序的时候,都会完成一定的功能,比如说浏览器帮我们打开网页,为了保证其独立性,就需要一个专

Java多线程之 -- 进程和线程

Java多线程之 – 进程和线程 概念 进程 程序的动态执行过程 包括占用的资源(内存.CPU)和线程 线程 线程是程序中最小的执行单位 一个进程有多个线程 线程共享进程的资源 进程和线程的区分 我们可以想象为进程为班级而线程是邦奇中得每一个学生 线程之间的交互 互斥,类似于每一个学生都为了第一名而你争我让,线程也是,都想抢占CPU的资源 同步,当举行运动会的时候,大家都团结一心,彼此共享自己的资源 Thread.Runnable Thread Introduction Thread 是Java

操作系统中的进程与线程

操作系统中的进程与线程 转自:http://www.cnblogs.com/CareySon/archive/2012/05/04/ProcessAndThread.html 简介 在传统的操作系统中,进程拥有独立的内存地址空间和一个用于控制的线程.但是,现在的情况更多的情况下要求在同一地址空间下拥有多个线程并发执行.因此线程被引入操作系统. 为什么需要线程? 如果非要说是为什么需要线程,还不如说为什么需要进程中还有其它进程.这些进程中包含的其它迷你进程就是线程. 线程之所以说是迷你进程,是因为