Java线程浅学习



线程概述

线程是程序运行的基本执行单位,当操作系统执行一个程序时,会创建一个进程,而这个进程至少创建一个线程(主线程)作为这个程序的入口点。所以,在操作系统中运行的程序都至少有一个主线程。

进程和线程是现代操作系统必不可少的运行模型,在操作系统中可以有多个进程,这些进程包括系统进程(系统内部创建的进程)和用户进程(用户程序创建的进程),一个进程可以有多个线程。进程之间不存在内存共享,就是说,系统中的进程都是在各自的内存空间中运行的。但是一个进程中的线程可以共享系统分配给这个进程的内存空间。

线程不仅可以共享进程的内存,而且还拥有一个属于自己的内存空间,叫线程栈。是在建立线程时系统分配的,主要是保护线程内部所使用的数据。

创建线程的方法

在Java中创建线程的方法有两种:使用
Thread类和使用Runnable接口。

  1. 使用thread类创建

    如下所示:

    NewThth=new NewTh();

    NewTh th1=new NewTh();

    Thread td=new Thread(th);

    Threadtd1=new Thread(th1);

    td.start();

    td1.start();

    这样就启动了线程。

    一个普通的Java类只要继承了thread类,就可以成为一个线程类,如下面的代码:

    packagecom.cn.test;

    //线程就是为了更好地利用CPU,提高程序运行速率的!

    publicclass MyThread extends Thread{

    private int i ;

    public void run(){

    for (int i = 0;i<100;i++){

    System.out.println(Thread.currentThread().getName()+""+i);

    }

    }

    public static void main(String[] args) {

    new MyThread().run();

    //run()方法当作普通方法的方式调用,程序还是要顺序执行,还是要等待run方法体执行完毕后才可继续执行下面的代码。

    new MyThread().start();

    //start()方法来启动线程,真正实现了多线程运行,这时无需等待run方法体代码执行完毕而直接继续执行下面的代码。

    new MyThread().start();

    }

    }

  2. 使用Runnable接口

    使用接口Runnable创建一个线程时,需要调用该对象的run方法。

    如代码:

    packagecom.cn.test;

    //线程就是为了更好地利用CPU,提高程序运行速率的!

    publicclass MyThread1 {

    public static void main(String[] args) {

    NewTh th=new NewTh();

    NewTh th1=new NewTh();

    Thread td=new Thread(th);

    Thread td1=new Thread(th1);

    th.run();

    th1.run();

    //th.start();  
    th对象没有start()方法,在这里run()方法相当于方法的调用,

    td.start();

    td1.start();

    td.run();

    td1.run();

    }

    }

    classNewTh implements Runnable{

    int i=0;

    @Override

    public void run() {

    // TODO Auto-generated method stub

    for(int i =0 ;i<20;i++){

    System.out.println(Thread.currentThread().getName()+"" +i);

    }

    System.out.println("金丝燕,未来无极限");

    }

    }

  3. 线程的启动

    通过以上的例子,可以发现继承了Thread类的线程启动执行start()方法和run()方法,而实现Runnable
    接口的只能执行run()方法,而这两个有什么区别那?

    Start:

    用start方法来启动线程,真正实现了多线程运行,这时无需等待run方法体执行完毕而直接继续执行下面的代码。通过Thread类的start()方法来启动一个线程,这时线程就会处于可运行状态,但并没有运行,一旦得到CPU时间片段就开始执行run方法,这时run()称为线程体,它包含了这个线程要执行的内容,Run方法执行结束,此线程终止。

    Run:

    run()方法只是类的一个普通方法,如果调用run方法,那么只用等run方法执行完毕才能执行下面的代码。

线程的状态

线程中除了有start和run方法来操作线程的状态,还有一些其他的方法来控制。

  1. 睡眠线程

    sleep(long millis)方法

    让线程停止一段时间,在sleep时间间隔期满后,线程不一定立即恢复执行,因为在这一时刻,其他线程正在运行而没有被调度为放弃执行,除非恢复过来的线程具有更高的优先级,或者正在运行的线程因为其他原因而被阻塞。sleep(long millis,int nanos)方法,millis
    - 以毫秒为单位的休眠时间,nanos-
    要休眠的另外 0-999999
    纳秒。

    如代码:public classMyThread extends Thread {

    public void run() {

    for (int i = 0; i < 100; i++) {

    if ((i) % 10 == 0) {

    System.out.println("-------" + i);

    }

    System.out.print(i);

    try {

    Thread.sleep(1000);

    System.out.println("   
    线程睡眠1秒!");

    } catch (InterruptedException e) {

    e.printStackTrace();

    }

    }

    }

    public static void main(String[] args) {

    new MyThread().start();

    }

    }

    wait()方法

    让线程等待一段时间,或者是在其他线程调用此对象的 notify()
    方法或 notifyAll()
    方法前等待

    等待对象的同步锁,需要获得该对象的同步锁才可以调用这个方法,否则编译可以通过,但运行时会收到一个异常:IllegalMonitorStateException。调用任意对象的
    wait() 方法导致该线程阻塞,该线程不可继续执行,并且该对象上的锁被释放。

notify()方法

唤醒在等待该对象同步锁的线程(只唤醒一个,如果有多个在等待),注意的是在调用此方法的时候,并不能确切的唤醒某一个等待状态的线程,而是由JVM确定唤醒哪个线程,而且不是按优先级。

调用任意对象的notify()方法则导致因调用该对象的wait()方法而阻塞的线程中随机选择的一个解除阻塞(但要等到获得锁后才真正可执行)。

notifyAll()

唤醒所有等待的线程,注意唤醒的是notify之前wait的线程,对于notify之后的wait线程是没有效果的。

resume()方法和suspend()

suspend()方法使得线程进入阻塞状态,并且不会自动恢复,必须调用其对应的resume()方法才能使得线程重新进入可执行状态。

resume方法和suspend方法在一起使用,具有固有的死锁倾向。如果目标线程挂起时在保护关键系统资源的监视器上保持有锁,则在目标线程重新开始以前任何线程都不能访问该资源,如果重新开始目标线程的线程想在调用resume之前锁定该监视器,则会发生死锁,这类死锁通常会证明自己是“冻结”的进程。

stop()

stop()方法是不安全的,该方法已经过时,在调用Thread.stop方法的时候,会即刻抛出ThreadDeath异常,同时会释放该线程的所有的锁。调用stop方法会产生不完整的残废数据,而多线程编程最最基础的就是保证数据的完整性,所以不建议使用stop方法。

interrupt()

请移步http://blog.csdn.net/cxy782255346/article/details/38472851

isAlive()

用于测试线程是否处于活动状态,如果线程已经启动且尚未终止,则为活动状态。如果该线程处于活动状态则返回TRUE,否则返回FALSE。

join()

join()用于停止当前线程而运行别的线程。换句话说就是,join()方法可以把两个交替执行的线程合并为顺序执行的线程,比如在线程B中调用了线程A中的join()方法,那么就会等到线程A执行完之后,B线程才会继续执行。

时间: 2024-10-21 15:16:54

Java线程浅学习的相关文章

Java 线程池学习

Reference: <创建Java线程池>[1],<Java线程:新特征-线程池>[2], <Java线程池学习>[3],<线程池ThreadPoolExecutor使用简介>[4],<Java5中的线程池实例讲解>[5],<ThreadPoolExecutor使用和思考>[6] [1]中博主自己通过ThreadGroup实现一个线程池(挺方便理解的),使用的是jdk1.4版本,Jdk1.5版本以上提供了现成的线程池. [2]中介绍

Java线程池学习

一.实现Java多线程的方法 1.继承Thread类创建多线程 Thread类本质实现了Runnable接口.启动线程为start0()方法.是个native方法. 1 public class ThreadProcess extends Thread { 2 3 @Override 4 public void run(){ 5 long lastTime = System.currentTimeMillis(); 6 for(int i = 0; i < 1; i++){ 7 int ele

java 线程基础学习

今天趁空闲时间看了点线程方面的知识 首先看的是volatile关键字,按照我之前书上看到的一点知识,自己的理解是,volatile关键字会阻止编译优化,因为cpu每次读取数据是并不是从高速缓存中读取,而是取内存中的数据.这是自己的一点简单的理解,可能有错误.我之前只是看了点线程方面的知识,只是在自己写代码的时候很少(根本没用到),就是自己学习的时候跟着书上敲了代码. 实习的时候要我写个压力测试,1000个线程同时发请求,统计请求失败的次数,我用了volatile关键字,但是感觉有点问题,今天就测

关于java线程浅谈五: Condition条件

在面试的过程当中,在面试官提出问题的时候,往往会就问题本身引申出较深层次的问题.比如:你使用过with语句吗?我的回答是:with语句经常适用于对资源进行访问的场合,确保在访问的过程中不管是否发生异常都会指执行必要的清理操作,比如文件的自动关闭以及线程中锁的自动获取与释放.面试官紧接着问,那你知道为什么with语句能够使文件正确关闭,一下子把我问闷了,只能依稀记得with语句会开辟出一块独立环境来执行文件的访问,类似沙盒机制.面试官对这个答案不置可否,算是勉强通过了.所以知其然更要知其所以然.在

java线程API学习 线程池ThreadPoolExecutor(转)

线程池ThreadPoolExecutor继承自ExecutorService.是jdk1.5加入的新特性,将提交执行的任务在内部线程池中的可用线程中执行. 构造函数 ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, Rejected

JAVA线程的学习笔记

---恢复内容开始--- 线程的使用: 让线程终止的办法 线程的终止只能由线程自己决定,所以我们在run()方法中使用一个标志位while( BOOlean B)来执行代码 void join( ) 或者  void join(long millis)假设在A线程中调用B线程的这个方法,A线程会被阻塞. 只有在B线程执行完毕或者执行了millis这个参数的时间后,A线程才能恢复执行 set Deanon( true)  设置为守护线程,当进程中没有用户线程时,虚拟机退出,默认的是用户线程 Thr

java线程池学习(一)

前言 在实际工作中,线程是一个我们经常要打交道的角色,它可以帮我们灵活利用资源,提升程序运行效率.但是我们今天不是探讨线程!我们今天来聊聊另一个与线程息息相关的角色:线程池.本篇文章的目的就是全方位的解析线程池的作用,以及jdk中的接口,实现以及原理,另外对于某些重要概念,将从源码的角度探讨. tip:本文较长,建议先码后看. 线程池介绍 首先我们看一段创建线程并且运行的常用代码: for (int i = 0; i < 100; i++) { new Thread(() -> { Syste

Java线程池学习总结

一 使用线程池的好处 池化技术相比大家已经屡见不鲜了,线程池.数据库连接池.Http 连接池等等都是对这个思想的应用.池化技术的思想主要是为了减少每次获取资源的消耗,提高对资源的利用率. 线程池提供了一种限制和管理资源(包括执行一个任务). 每个线程池还维护一些基本统计信息,例如已完成任务的数量. 这里借用<Java 并发编程的艺术>提到的来说一下使用线程池的好处: 降低资源消耗.通过重复利用已创建的线程降低线程创建和销毁造成的消耗. 提高响应速度.当任务到达时,任务可以不需要的等到线程创建就

java线程的学习

接口 Runable 属性:target 方法:void run() 类 Thread 方法:void start()用来启动一个线程 void run() 线程启动后执行的方法 Sting getName() void setName(String) Thread currentThread()  返回Thread的引用,这个引用指向当前代码的线程 void sleep(long)  线程挂起(暂停),参数为毫秒数,5000为5秒(sleep是个静态方法) 构造方法:Thread(Runabl