博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
java高级编程 线程详解(/看这一篇就懂了/)
阅读量:3961 次
发布时间:2019-05-24

本文共 15395 字,大约阅读时间需要 51 分钟。

一、线程

线程:程序内的单序列控制流

单线程,每次只能执行一项任务,而为了节省时间并有了多线程。
多线程的优点:

  • 改进性能
  • 最小化系统资源使用
  • 简化程序结构

缺点

  • 竞争情况
  • 死锁情况
  • 锁饥饿

二、Thread类

Java.lang.Thread类用于构造和访问多线程应用程序中的单个线程,可以使用Thread类或Runnable接口创建。
方法包括有:

方法名 作用
int getPriority() 返回线程的优先级
String void sleep() 使线程休眠几秒(单位为毫秒)
void start() 通过调用run方法启动线程执行
sattic Thread currentThread() 返回当前线程对象的引用
boolean isAlive() 检查线程的存在性
public final void join() 允许线程等待直到调用该方法的线程终止为止
void interrupt() 用于是线程执行时中断
static boolean interrupted() 用于确定当前线程是否被其他线程中断

案例:

package 使用线程;public class MainThreadDemo {
public static void main(String args[]) {
Thread t = Thread.currentThread(); System.out.println(" 当前线程: " + t); //t包含了[线程名,优先级,线程组] t.setName("MainThread"); System.out.println("名称更改后的当前线程: " + t); System.out .println("当前线程将休眠10秒 "); try {
t.sleep(10000);//在休眠期间可以调用另一个interrupt()函数打断这个线程。 } catch (InterruptedException e) {
System.out.println("主线程中断"); } System.out.println("等待10秒后...当前线程正在退出"); }}

实现线程的最简单的俩种方法

1 继承thread类,在该类中重写run方法,代码如下:

  • 部分方法的实现

1.0 isAlive()方法,如果线程还在运行返回true,反之为false。

package 使用线程;//isAlive()方法,用于检查线程是否存活。class NewThreadClass implements Runnable{
Thread t; //线程引用 NewThreadClass() {
t = new Thread(this,"ChildThread" ); System.out.println("Thread created: " + t); t.start(); } public void run() {
try {
for(int i=1;i<=5;i++) {
System.out.println(t + "loop :" + i); Thread.sleep(100); } } catch( InterruptedException obj) {
System.out.println("Thread :" + t + "interrupted"); } }}public class IsAliveDemo {
public static void main(String args[]) {
NewThreadClass obj = new NewThreadClass(); System.out.println(obj.t + "is alive ? : " + obj.t.isAlive()); try {
for(int i=1;i<=5;i++) {
System.out.println("主螺纹环:" + i); Thread.sleep(200); } } catch(InterruptedException e) {
System.out.println("主线程中断");} System.out.println(obj.t + "is alive ? : " +obj.t.isAlive()); System.out.println("Main Thread is exiting"); }}

2.0 join()方法,允许线程等待直到调用该方法的线程终止为止,此外join()方法使您能够指定你等待的线程终止所需的最长时间。

package 使用线程;class ChildThread implements Runnable {
Thread t; ChildThread() {
t = new Thread(this, "ChildThread"); System.out.println("Thread created: " + t); t.start(); } public void run() {
try {
for (int i = 1; i <= 5; i++) {
System.out.println(t + "loop :" + i); Thread.sleep(500); } } catch (InterruptedException obj) {
System.out.println("Thread :" + t + "interrupted"); } }}public class JoinDemo {
public static void main(String args[]) {
ChildThread obj = new ChildThread(); System.out.println(obj.t + "is alive ? : " + obj.t.isAlive()); try {
System.out .println("Main thread waiting for child thread to finish"); obj.t.join(); } catch (InterruptedException e) {
System.out.println(" 主线程被打断 "); } System.out.println(obj.t + "is alive ? : " + obj.t.isAlive()); System.out.println("Main Thread is exiting"); }}

三、线程的生命周期

在这里插入图片描述

  • 新生
    创建Thread类的事例后,线程进入到新生状态,
Thread newThread = new Thread (this,"threadname")		/*新的线程是Thread类的空对象,没有分配系统资源,		必须调用start()方法来启动线程。*/
  • 可运行
    当start()方法调用时,线程进入可运行状态。
  • 不可运行
    1,休眠 调用sleep()方法
    2,等待 调用Object类的wait()方法
    3,正被其他线程阻止,线程如果被I/O操作阻止,进入不可运行状态
  • 死亡
    1,run()方法中的语句都已执行
    2,向线程对象分配null值
    3,通过stop()方法停止线程执行来杀死线程

四、创建多线程(一)通过继承Thread类

package 使用线程;随机出现障碍物//创建多线程,使用thread类import java.awt.Color;import java.util.Random;//产生随机数的包import javax.swing.*;public class Race extends Thread {
String ThreadName; JLabel l; JPanel l1, l2, l3; JFrame fr; public Race() {
buildGUI(); } public Race(String s) {
super(s); //调用父类的构造函数, } public void run() {
if (Thread.currentThread().getName().equals("ObstacleA")) {
runObstacleA(); } if (Thread.currentThread().getName().equals("ObstacleB")) {
runObstacleB(); } if (Thread.currentThread().getName().equals("ObstacleC")) {
runObstacleC(); } } public void runObstacleA() {
Random ran = new Random(); int s = ran.nextInt(1000); //s保存了纵坐标,随机 for (int i = -10; i < 400; i++) {
//i值自减 ,横坐标为i。表示A向右移动 l1.setBounds(i, s, 20, 20); try {
Thread.sleep(5); } catch (Exception e) {
System.out.println(e); } } runObstacleC(); } public void runObstacleB() {
Random ran = new Random(); int r = ran.nextInt(180); for (int i = -10; i < 400; i++) {
l2.setBounds(i, r, 20, 20); try {
Thread.sleep(11); } catch (Exception e) {
System.out.println(e); } } runObstacleA(); } public void runObstacleC() {
Random ran = new Random(); int m = ran.nextInt(10); for (int i = -10; i < 400; i++) {
l3.setBounds(i, m, 20, 20); try {
Thread.sleep(10); } catch (Exception e) {
System.out.println(e); } } runObstacleB(); } public void buildGUI() {
fr = new JFrame("多线程测试"); fr.setVisible(true); fr.setSize(400, 200); fr.setLayout(null); l = new JLabel(""); l.setBounds(10, 10, 400, 20); fr.add(l); l1 = new JPanel(); l1.setSize(20, 20); l1.setBackground(Color.red); l1.setBounds(10, 40, 20, 20); fr.add(l1); l2 = new JPanel(); l2.setSize(20, 20); l2.setBackground(Color.blue); l2.setBounds(10, 80, 20, 20); fr.add(l2); l3 = new JPanel(); l3.setSize(20, 20); l3.setBackground(Color.black); l3.setBounds(10, 120, 20, 20); fr.add(l3); } public static void main(String args[]) {
Race obj = new Race(); Thread Obstacle1 = new Thread(obj); Thread Obstacle2 = new Thread(obj); Thread Obstacle3 = new Thread(obj); Obstacle1.setName("ObstacleA"); Obstacle2.setName("ObstacleB"); Obstacle3.setName("ObstacleC"); Obstacle1.start(); Obstacle2.start(); Obstacle3.start(); }}

(二)实现Runnable接口

import java.awt.Color;import java.awt.Font;import javax.swing.*;public class CountdownTimer implements Runnable {
JTextField tf; JLabel l; JFrame fr; public void run() {
buildGUI(); } void display() {
for (int i = 60; i >= 0; i--) {
try {
Thread.sleep(1000); String s = Integer.toString(i); tf.setText(" "+ s + " seconds to go.."); } catch (Exception e) {
System.out.println(e); } } JOptionPane.showMessageDialog(fr, "Time Up !!!!"); tf.setText(""); tf.setEnabled(false); } public void buildGUI() {
fr = new JFrame("Countown Timer"); JPanel p = new JPanel(); l = new JLabel(""); tf = new JTextField(15); tf.setEnabled(false); Font f = new Font("Verdana", 0, 18); tf.setFont(f); tf.setBackground(Color.BLACK); p.setBackground(Color.blue); fr.add(p); p.add(tf); p.add(l); fr.setVisible(true); fr.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); fr.setSize(300, 100); fr.setResizable(false); display(); } public static void main(String args[]) {
CountdownTimer obj = new CountdownTimer(); Thread CountdownThread = new Thread(obj); CountdownThread.start(); }}

二,使用多线程

创建多线程

1,继承Thread类

package 使用线程;//创建多线程,使用thread类import java.awt.Color;import java.util.Random;import javax.swing.*;public class Race extends Thread {
String ThreadName; JLabel l; JPanel l1, l2, l3; JFrame fr; public Race() {
buildGUI(); } public Race(String s) {
super(s); //调用父类的构造函数, } public void run() {
if (Thread.currentThread().getName().equals("ObstacleA")) {
runObstacleA(); } if (Thread.currentThread().getName().equals("ObstacleB")) {
runObstacleB(); } if (Thread.currentThread().getName().equals("ObstacleC")) {
runObstacleC(); } } public void runObstacleA() {
Random ran = new Random(); int s = ran.nextInt(1000); //s保存了纵坐标,随机 for (int i = -10; i < 400; i++) {
//i值自减 ,横坐标为i。表示A向右移动 l1.setBounds(i, s, 20, 20); try {
Thread.sleep(5); } catch (Exception e) {
System.out.println(e); } } runObstacleC(); } public void runObstacleB() {
Random ran = new Random(); int r = ran.nextInt(180); for (int i = -10; i < 400; i++) {
l2.setBounds(i, r, 20, 20); try {
Thread.sleep(11); } catch (Exception e) {
System.out.println(e); } } runObstacleA(); } public void runObstacleC() {
Random ran = new Random(); int m = ran.nextInt(10); for (int i = -10; i < 400; i++) {
l3.setBounds(i, m, 20, 20); try {
Thread.sleep(10); } catch (Exception e) {
System.out.println(e); } } runObstacleB(); } public void buildGUI() {
fr = new JFrame("多线程测试"); fr.setVisible(true); fr.setSize(400, 200); fr.setLayout(null); l = new JLabel(""); l.setBounds(10, 10, 400, 20); fr.add(l); l1 = new JPanel(); l1.setSize(20, 20); l1.setBackground(Color.red); l1.setBounds(10, 40, 20, 20); fr.add(l1); l2 = new JPanel(); l2.setSize(20, 20); l2.setBackground(Color.blue); l2.setBounds(10, 80, 20, 20); fr.add(l2); l3 = new JPanel(); l3.setSize(20, 20); l3.setBackground(Color.black); l3.setBounds(10, 120, 20, 20); fr.add(l3); } public static void main(String args[]) {
Race obj = new Race(); Thread Obstacle1 = new Thread(obj); Thread Obstacle2 = new Thread(obj); Thread Obstacle3 = new Thread(obj); Obstacle1.setName("ObstacleA"); Obstacle2.setName("ObstacleB"); Obstacle3.setName("ObstacleC"); Obstacle1.start(); Obstacle2.start(); Obstacle3.start(); }}

2、实现runnable()接口

package 使用线程;import java.awt.Color;import java.util.Random;import javax.swing.*;public class Race1 implements Runnable {
//通过接口 String ThreadName; JLabel l; JPanel l1, l2, l3; JFrame fr; public Race1() {
buildGUI(); } public void run() {
if (Thread.currentThread().getName().equals("ObstacleA")) {
runObstacleA(); } if (Thread.currentThread().getName().equals("ObstacleB")) {
runObstacleB(); } if (Thread.currentThread().getName().equals("ObstacleC")) {
runObstacleC(); } } public void runObstacleA() {
Random ran = new Random(); int s = ran.nextInt(1000); for (int i = -10; i < 400; i++) {
l1.setBounds(i, s, 20, 20); try {
Thread.sleep(5); } catch (Exception e) {
System.out.println(e); } } runObstacleC(); } public void runObstacleB() {
Random ran = new Random(); int r = ran.nextInt(180); for (int i = -10; i < 400; i++) {
l2.setBounds(i, r, 20, 20); try {
Thread.sleep(11); } catch (Exception e) {
System.out.println(e); } } runObstacleA(); } public void runObstacleC() {
Random ran = new Random(); int m = ran.nextInt(10); for (int i = -10; i < 400; i++) {
l3.setBounds(i, m, 20, 20); try {
Thread.sleep(10); } catch (Exception e) {
System.out.println(e); } } runObstacleB(); } public void buildGUI() {
fr = new JFrame("Moving objects"); fr.setVisible(true); fr.setSize(400, 200); fr.setLayout(null); l = new JLabel(""); l.setBounds(10, 10, 400, 20); fr.add(l); l1 = new JPanel(); l1.setSize(20, 20); l1.setBackground(Color.red); l1.setBounds(10, 40, 20, 20); fr.add(l1); l2 = new JPanel(); l2.setSize(20, 20); l2.setBackground(Color.blue); l2.setBounds(10, 80, 20, 20); fr.add(l2); l3 = new JPanel(); l3.setSize(20, 20); l3.setBackground(Color.black); l3.setBounds(10, 120, 20, 20); fr.add(l3); } public static void main(String args[]) {
Race obj = new Race(); Thread Obstacle1 = new Thread(obj); Thread Obstacle2 = new Thread(obj); Thread Obstacle3 = new Thread(obj); Obstacle1.setName("ObstacleA"); Obstacle2.setName("ObstacleB"); Obstacle3.setName("ObstacleC"); Obstacle1.start(); Obstacle2.start(); Obstacle3.start(); }}

五、线程优先级

1,优先级:JRE基于线程优先级执行线程。由于CPU一个时间只能执行一个线程,JRE通过使用固定优先级调度线程,每一个线程都有一个优先级。

2,定义线程优先级:是介于1到10之间的整数,如果处理器遇到优先级更高的其他线程,那么当前线程将会被推后。如果较高优先级的线程停止或变为不可运行,那么下一个较低的优先级的线程开始执行。如果线程正在等待I/O操作,那么将该线程在队列中将会被其他线程推后。
3,设置线程优先级 setPriority()
默认值是 NORM_PRIORITY
如果给定的优先级参数不在范围内,将会抛出IllegalArgumentException(非法参数)异常

package 使用线程;class ChildThread1 implements Runnable{
Thread t; ChildThread1(int p) {
t = new Thread(this,"ChildThread" ); t.setPriority(p); System.out.println("Thread created: " + t); } public void run() {
try {
for(int i=1;i<=5;i++) {
System.out.println(t + "loop :" + i); Thread.sleep(500); } } catch( InterruptedException obj) {
System.out.println("Thread :" + t + "interrupted");} }}public class Priority {
public static void main(String args[]) {
ChildThread1 obj1 = new ChildThread1(Thread.NORM_PRIORITY - 2); ChildThread1 obj2 = new ChildThread1(Thread.NORM_PRIORITY + 2); ChildThread1 obj3 = new ChildThread1(Thread.NORM_PRIORITY + 3); obj1.t.start(); obj2.t.start(); obj3.t.start(); try{
System.out.println("Main thread waiting for child thread to finish"); obj1.t.join(); obj2.t.join(); obj3.t.join(); } catch(InterruptedException e) {
System.out.println("Main thread is interrupted");} System.out.println(obj1.t + "is alive ? : " + obj1.t.isAlive()); System.out.println(obj2.t + "is alive ? : " + obj2.t.isAlive()); System.out.println(obj3.t + "is alive ? : " + obj3.t.isAlive()); System.out.println("Main Thread is exiting"); } }

六、CPU调度算法

FCFS 先到先算 frist come frist server

SJF 最短作业优先 shortest job frist
SRTF shortest Remaning Time first 抢占的SJF算法
FPPS 基于优先权的调度算法

七、线程同步

同步是指:协调同步

实例在于当俩个线程需要共享数据的时候,为了避免错误,比如协调好他们的活动。比如,当网上买票时,只剩下一张票的时候,一个线程开始访问,我们这个时候就应该避免在此期间另一个线程也访问进来,导致一个座位售出多张票。


线程的同步确保了当俩个或者多个线程需要访问共享资源时,一次只能有一个线程使用该资源,实现的方法如下

  • 使用同步方法
  • 使用同步语句

1 同步方法,

直接在需要同步的方法前加上synchronized关键字,

public  synchronized void getData()    {
System.out.println("Got data:" + d); }

2 同步语句

同步对此类的对象的访问,把对象定义的方法调用放置在synchronized 块中,

synchronized(obj){
System.out.println("Got data:" + d);}

实现线程间的通信

线程间的通信是指:线程可以通过其他线程任务以完成,
使用的各种方法

方法 描述
wait( ) 通知当前线程离开监视程序的控制并等待,直到其他线程调用notify()方法为止
nodify( ) 唤醒正在等待对象的监视程序得到执行的单个线程,如果有多个将随机取一个
nodifyAll() 唤醒所有

案例:

package 实现线程同步与并发;class SynchronizedMethods {
int d; boolean flag = false; synchronized int getData() {
if (!flag) {
try {
wait(); } catch (InterruptedException e) {
System.out.println(" Exception caught"); } } System.out.println("得到数据:" + d); flag = false; notify(); return d; } synchronized void putData(int d) {
if (flag) {
try {
wait(); } catch (InterruptedException e) {
System.out.println(" Exception caught"); } } this.d = d; flag = true; System.out.println("有价值的数据:" + d); notify(); }}class Producer implements Runnable {
SynchronizedMethods t; public Producer(SynchronizedMethods t) {
this.t = t; new Thread(this, "Producer").start(); System.out.println("制作人呼叫"); } public void run() {
int data = 700; while (t.d<708) {
data = data + 1; t.putData(data); } }}class Consumer implements Runnable {
SynchronizedMethods t; public Consumer(SynchronizedMethods t) {
this.t = t; new Thread(this, "Consumer").start(); System.out.println("接到消费者的电话"); } public void run() {
while (true) {
t.getData(); } }}public class InterThreadComm {
public static void main(String args[]) {
SynchronizedMethods obj1 = new SynchronizedMethods(); Producer p = new Producer(obj1); Consumer c = new Consumer(obj1); }}

转载地址:http://ktmzi.baihongyu.com/

你可能感兴趣的文章