Java多线程编程(一)

  1. 首先要搞清楚进程和线程的概念:
    • 进程:进程就是程序的一次执行,它是进程实体(程序段、数据、PCB)的运行过程,是系统进行资源分配和调度的一个独立单位。eg:电脑上都会安装很多PC端的软件,比如QQ,你的QQ登录运行就是一个进程。
    • 线程:线程是调度和执行的基本单位。可以理解为是进程中独立运行的子任务,比如你登录QQ的时候,文件的传输以及视频通话等都是一个进程。
    • 进程与线程的关系:线程是进程中的运行实体;一个进程可以有多个线程;一个进程中至少包含一个线程,称为主线程;进程就相当于线程的载体;进程和线程是不同的操作系统资源管理方式。
  2. 多线程编程的好处:多线程并发执行可以提高程序的效率,CPU不会因为某个线程需要等待资源而进入空闲状态,多个线程共享内存堆。
  3. 如何创建线程?
    主要有两种方式:一种是继承Thread类,另一种是实现Runnable接口;根据Thread类的结构
    public class Thread implements Runnable
    可以看出Thread类实现了Runnable接口,他们之间是多态关系;
    • 通过继承Thread类实现线程的创建
package threadlearn.thread;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class myThread extends Thread {
    @Override
    public void run() {
        super.run();
        System.out.println("线程:"+Thread.currentThread().getName());
    }
}


package threadlearn.test;

import threadlearn.runnable.MyRunnable;
import threadlearn.thread.myThread;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class Run {
    public static void main(String[] args) {
        myThread myThreadDemo=new myThread();
        myThreadDemo.start();   //启动线程
    }
}
  • 实现Runnable接口
    该接口中只有一个run()方法,通过实现Runnable接口创建的线程可以用于资源共享。eg:多个线程基于一个Runnable对象建立起来的时候,他们就会共享Runnable对象的资源。
package threadlearn.runnable;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class MyRunnable implements Runnable {
    @Override
    public void run() {
        System.out.println("线程:"+Thread.currentThread().getName()+"正在运行中!");
    }
}

package threadlearn.test;

import threadlearn.runnable.MyRunnable;
import threadlearn.thread.myThread;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class Run {
    public static void main(String[] args) {

        Runnable runnable=new MyRunnable();
        Thread thread=new Thread(runnable);
        thread.start();//启动线程
        System.out.println(thread.getName()+"结束");

        System.out.println("线程"+Thread.currentThread().getName()+"运行结束!");

    }
}

  1. start()方法用于启动线程,它会通知系统当前线程已经准备就绪,等待系统分配时间来执行其对应的run()方法,但是执行 start()方法的顺序并不是代表线程启动的顺序,还有就是 start()方法不会被重复的调用;无参数的run()方法是会自动执行的,新线程会自动执行相应的run()方法。
  2. 实例变量与线程安全:
    • 共享数据的情况下,多个线程可以访问同一个变量,比如实现投票系统的时候多个线程可以同时处理同一个人的票数。
    • 多个线程同时访问一个变量的时候会出现非线程安全(主要是指多个线程对同一个对象中的同一个实例变量进行操作的时候会出现值被更改、值不同步的 情况,进而影响程序的执行流程) 的问题,这时需要使用synchronized关键字实现同步。
    • synchronized关键字可以在任意对象及方法上加锁,而加锁的这块代码成为“互斥区”或“临界区”
  3. currentThread()方法获取的是CPU当前正在调用的线程,而this是当前的类对象。
  4. isAlive()方法的功能是判断当前线程是否处于活动状态。活动状态就是线程已经启动且未终止,线程处于正在运行或者准备开始的状态就认为线程是存活的。
  5. sleep()的作用是在指定的毫秒数内让当前“正在执行的线程”休眠(暂停执行)。“正在执行的线程”是指this.currentThread()返回的线程。
  6. getId()方法是获取线程的唯一标识。
  7. 终止线程:
    有以下三种方法:
    • 使用退出标志,使线程正常退出,也就是run方法完成后线程中止。
    • 使用stop方法强行终止线程,但是并不推荐使用该方法。stop方法和suspend方法及resume方法一样都是作废过期的方法,使用它们可能产生不可预料的结果。
    • 使用interrupt方法中断线程。
  8. 判断线程是否是停滞状态:
    • this.interrupted():测试当前线程是否已经中断.(测试的是当前线程是否中断)
    • this.isInterrupted():测试线程是否已经中断.
    • interrupt方法会清除线程的中断状态:也就是说,如果原线程是中断状态,调用了interrupt方法之后线程中的中断标记会被清除,当再次对该线程调用interrupt方法的时候不会再显示线程中断。
  9. 异常法终止线程:
package threadlearn.thread;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class MyThreadDemo4 extends Thread {
    @Override
    public void run() {
        super.run();
        try{
            for (int i = 0; i < 500000; i++) {
                if(this.isInterrupted()){
                    System.out.println("已经是停止状态,将要退出!");
                    throw new InterruptedException();   //抛出中断异常
                }
                System.out.println("i="+i+1);
            }
        }catch (InterruptedException e){
            System.out.println("进入MyThreadDemo4.java类的run方法中的catch!");
            e.printStackTrace();
        }
    }
}


package threadlearn.test;

import threadlearn.thread.MyThreadDemo4;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class testMyThreadDemo4 {
    public static void main(String[] args) {
        try{
            MyThreadDemo4 myThreadDemo4=new MyThreadDemo4();
            myThreadDemo4.start();
            Thread.sleep(2000);
            myThreadDemo4.interrupt();
        }catch (InterruptedException e){
            System.out.println("main catch  !");
            e.printStackTrace();
        }
        System.out.println("end!!!");
    }
}

这里写图片描述


  1. yield()方法的作用是放弃当前的CPU资源,将它让给其他的任务去占用CPU执行时间,但是放弃的时间不确定,可能刚刚放弃马上又获得CPU时间片.
  2. 线程的优先级:
    • 在操作系统中,线程可以划分优先级,优先级较高的线程得到的CPU资源较多也就是CPU优先执行优先级较高的线程对象中的任务.
    • 设置线程的优先级使用setPriority()方法.
    • 在Java中优先级分为1-10级,如果小于1或者大于10则JDK会抛出异常throw new IllegalArguementException();
    • 线程的优先级具有继承性:如果B线程是由A线程启动的,那么B线程将拥有和A线程相同的优先级。
    • 当线程的优先级的等级差距很大的时候,谁先执行完和代码的调用顺序无关。高优先级的线程总是大部分先执行完。
package threadlearn.thread;

import java.util.Random;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class MyThreadDemo5 extends Thread {
    @Override
    public void run() {
        long beginTime=System.currentTimeMillis();
        long addResult=0;
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 5000; j++) {
                Random random=new Random();
                random.nextInt();
                addResult=addResult+i;
            }
        }
        long endTime=System.currentTimeMillis();
        System.out.println("MyThreadDemo5 use time="+(endTime-beginTime));
    }
}




package threadlearn.thread;

import java.util.Random;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class MyThreadDemo6 extends Thread {
    @Override
    public void run() {
        long beginTime=System.currentTimeMillis();
        long addResult=0;
        for (int i = 0; i < 10; i++) {
            for (int j = 0; j < 50000; j++) {
                Random random=new Random();
                random.nextInt();
                addResult=addResult+i;
            }
        }
        long endTime=System.currentTimeMillis();
        System.out.println("MyThreadDemo6 use time="+(endTime-beginTime));
    }
}



package threadlearn.test;

import threadlearn.thread.MyThreadDemo5;
import threadlearn.thread.MyThreadDemo6;

/**
 * Created by xpengfei on 2017/9/12.
 */
public class testPriority {
    public static void main(String[] args) {
        for (int i = 0; i < 6; i++) {
            MyThreadDemo5 myThreadDemo5=new MyThreadDemo5();
            myThreadDemo5.setPriority(10);  //设置优先级为最高
            myThreadDemo5.start();  // 启动线程

            MyThreadDemo6 myThreadDemo6=new MyThreadDemo6();
            myThreadDemo6.setPriority(1);   //设置优先级最低
            myThreadDemo6.start();  //启动线程
        }
    }
}


这里写图片描述

  • 线程的优先级具有随机性,优先级较高的线程并不一定每一次都先执行完run方法中的任务。
  • 优先级高的线程运行的快。

1.用户线程和守护线程有什么区别?

当我们在Java程序中创建一个线程,它就被称为用户线程。一个守护线程是在后台执行并且不会阻止JVM终止的线程。当没有用户线程在运行的时候,JVM关闭程序并且退出。一个守护线程创建的子线程依然是守护线程。

2.可以直接调用Thread类的run()方法么?

当然可以,但是如果我们调用了Thread的run()方法,它的行为就会和普通的方法一样,为了在新的线程中执行我们的代码,必须使用Thread.start()方法。

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值