java高级编程 线程详解(/看这一篇就懂了/)

一、线程

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

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

缺点

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

二、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);
	}
}
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
根据定义,进程为一个数据结构及能在其上进行的一次操作, 它有两个基本特征, 1:进程是可用于资源的独立单位, 2:进程同时又是一个可独立调度和分派的基本单位, 这两个基本属性使之能够独立运行,也能够并发运行。但是在并发运行的时候,系统还需要执行一系列操作: 1、需要创建进程,并为之分配其所必需的资源。 2、撤销进程,对资源进行回收。 3、进程切换,它需要保留当前进程的CPU环境和设置新选中进程的CPU环境。 为此需要花费不少处理时间。正因为进程拥有资源,所以在并发执行进程的时候, 在创建、撤销和切换,系统需要付出较大的开销,因此,系统中设置的进程不能太多, 进程切换的频率也不能过高,这就限制了并发程度的提高。 为了解决这一问题,于是产生并引入了线程概念。 一个进程中可以包含一个或多个线程,一个线程就是程序内部的一条执行线索。 在单线程中,程序代码按调用顺序依次往下执行,不能实现两段程序代码同时交替运行的效果。如果一个程序中要实现两段程序代码同时交替运行,就需要产生多个线程,并指定每个线程上所要运行的程序代码段,这就是多线程。 程序启动运行时,就自动产生了一个线程,main方法就是在这个线程上运行的,当不再产生新的线程时,程序就是单线程

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

Modify_QmQ

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值