一、线程
线程:程序内的单序列控制流
单线程,每次只能执行一项任务,而为了节省时间并有了多线程。
多线程的优点:
- 改进性能
- 最小化系统资源使用
- 简化程序结构
缺点
- 竞争情况
- 死锁情况
- 锁饥饿
二、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);
}
}