55.【Java 线程】

99 阅读9分钟

线程 Thread

1. 什么是进程?

正在运行中的应用程序,通常称为进程。每个进程都有自己独立的地址空间(内存空间),每当用户启动一个进程时,操作系统就会为该进程分配一个独立的内存空间,让应用程序在这个独立的内存空间中运行。

2.什么是线程?

main函数是线程、Thread t=new Thread()。出来的是线程,正常的情况下的方法不是线程。).
线程是一个轻量级的子进程,是最小的处理单元;是一个单独的执行路径。可以说:线程是进程的子集(部分)。

3.线程特点:

线程是独立的。如果在一个线程中发生异常,则不会影响其他线程。它使用共享内存区域。

4.进程和线程的区别:

1、容易创建新线程。但是,创建新进程需要重复父进程

2线程可以控制同一进程的其他线程**。进程无法控制兄弟进程,只能控制其子进程。

3、进程拥有自己的内存空间。线程使用进程的内存空间,且要和该进程的其他线程共享这个空间;而不是在进程中给每个线程单独划分一点空间。

4、(同一进程中的)线程在共享内存空间中运行,而进程在不同的内存空间中运行。

5、线程可以使用wait(),notify(),notifyAll()等方法直接与其他线程(同一进程)通信;而,进程需要使用“进程间通信”(IPC)来与操作系统中的其他进程通信。

5.多任务和线程:

在这里插入图片描述

多任务是指在系统中同时运行多个程序,如果只有一个处理器只有一个进程的一个指令被执行,可以使这些程序进行交替执行,由于间隔的时间短,这些程序看上去好像在同时运行.
如果将进程划分为线程,每个线程轮流占用处理器,可以减少并发时间.

(一)、线程(Thread)

1.线程的创建:

为什么要创建线程?

为了将进程划分为线程,要在程序中创建多个线程对象(java.lang.Thread)

2.线程的构造方法:

在这里插入图片描述

3.线程的成员方法:

在这里插入图片描述

4.静态成员函数:(调用的时候要用类名)

在这里插入图片描述

5.线程的创建:

在Java中,每个程序至少自动拥有一个主线程。如果需要使用其他线程,采用以下两种方式进行创建新的线程。
第一种:

继承(Thread)类,用它覆盖类方法中的run()方法.

import java.sql.SQLOutput;
import java.util.*;
import java.awt.*;
import java.lang.Math;
public class hello extends Thread {
    public void run(){
        for(int i=0;i<10;i++){
            System.out.println(currentThread().getName()+i);
        }
    }
    public static void main(String []avgs) {
        System.out.println(activeCount());   //当前线程活跃数目
        hello h1=new hello();  //创建新线程
        hello h2=new hello();  //创建新线程
        h1.start();  //导入线程
        h2.start();  //导入线程
        //Thread.currentThread().getThreadGroup().list();
        }
}

在这里插入图片描述

第二种:

编写一个类,使它实现java.lang.Runnable接口,然后在Thread构造函数中使用它.

import java.sql.SQLOutput;
import java.util.*;
import java.awt.*;
import java.lang.Math;
public class hello implements Runnable {
    public void run(){
        for(int i=0;i<10;i++){
            System.out.println(Thread.currentThread().getName()+" "+i);  //线程对象调用
        }
    }
    public static void main(String []avgs) {
        System.out.println(Thread.activeCount());   //当前线程活跃数目
        hello h1=new hello();  //接口对象
        Thread t1=new Thread(h1);  //把接口得对象传递给线程
        hello h2=new hello();  //接口对象
        Thread t2=new Thread(h2);//把接口得对象传递给线程
        t1.start();  //导入线程
        t2.start();  //导入线程
        //Thread.currentThread().getThreadGroup().list();   //得到调用线程的列表
        } 
}

在这里插入图片描述

(二)、线程的生命周期

创建(new)—>就绪(start)—>运行中(调度)------->死亡(run()结束)
阻塞:
1.等待阻塞: 运行中 调用(wait())函数的时候,如果调用notify()或则notifyAll() 就解除当前的阻塞进入到 就绪阶段.
2.互斥阻塞:运行中 调用synchronized()函数,试图获得某个对象的同步锁,如果该对象的同步锁已经被其他占用,则该线程被放入锁池中.
3.其他阻塞: 运行中 调用sleep()函数,join()方法

(三)、线程的优先级和调度:

线程的优先级范围i是1~10,最低是1,最高是10,默认是5.
获得优先级:

getPriority()  //用于获得线程的优先级

设置优先级

setPriority()  //用于设置优先级

1.线程的调度采用占先原则
2.相同优先级的线程,有分时和独占两种调度方式.

(四)、异常处理

1.error类:

包括了一些严重的。程序不能处理的系统错误,如同有内存不足,虚拟机错误、栈溢出等。这类错误主要由硬件问题引起的,与程序无关

2.Exception类

Exection类及其子类都是程序因考虑不周或不可控因素导致的错误,根据编译器是否对某类异常进行检查,Expection类分为非受检异常(运行异常)和受检异常(需要程序员处理)两种。

3.异常处理步骤:

  					try{}

可能出现的异常语句块,可能有错误,也可能没有错误。当try子句中的某个语句发生异常后,产生异常对象,终止当前正在执行的语句,后面的语句将不再执行,然后抛出异常对象

  					catch{}

根据try{}抛出的异常对象,那么catch进行从上倒下一直捕捉异常对象,进行一直捕捉,直到找到为止

  					finnaly{}

无论是否异常,finnaly子句依然正常执行

try{
	
}
catch(异常类型1, 异常对象){
		//处理类型1  (拆弹专家1)
}
catch(异常类型2, 异常对象){
		//处理类型2   (拆弹专家2)
}
finally{
  无论出现异常都要抛出
}

4.举列子:

错误信息:
在这里插入图片描述
捕捉错误:
在这里插入图片描述
手动修改错误:

在这里插入图片描述

(五)、漫天星辰

import java.awt.*;
import java.util.Random;

public class panel extends Panel implements Runnable {
    int x=10;
    int y=10;
    int size=30;
    int m=500;
    int n=350;
    int k=650;
    int s=200;
    int f=200;
    public void paint(Graphics g) {
        //绘画云朵
        g.setColor(Color.LIGHT_GRAY);
        g.fillOval(m,250,300,150);
        g.fillOval(n,300,300,100);
        g.fillOval(k,300,300,100);
        //绘画月亮
        Color c = new Color(255, 255, 0);
        g.setColor(c);
        g.fillOval(200, 200, 100, 100);
        Color c1 = new Color(0, 0, 0);
        g.setColor(c1);
        //绘制半月
        g.fillArc(s, f, 100, 100, 0, 360);
        //绘画星星
        Color c2 = new Color(255, 192, 203);
        g.setColor(c2);
        Font f = new Font("黑体", Font.BOLD, size);
        g.setFont(f);
        int i=0;
        Random r=new Random();
        while(i++<300){
            x=r.nextInt(1980)+1;
            y=r.nextInt(1024)+1;
            g.drawString("*", x, y);}
    }
    public void run(){  //覆盖线程的操作
        while(true){
            if(n>=1980){   //云朵
                n=350;   //左
                m=500;    //中
                k=650;    //右
            }
            if(f>310){   //半月
                s=200;
                f=200;
            }
            f++;
            s++;
            x++;
            y++;
            m++;
            k++;
            n++;
            try {
                Thread.sleep(30);
            }catch (Exception e){
                e.printStackTrace();
            }repaint();
        }
    }
}

主方法:

import java.sql.SQLOutput;
import java.util.*;
import java.awt.*;
import java.lang.Math;
public class hello  {
    public static void main(String []avgs) {
        Frame f=new Frame();
        f.setTitle("宝马");
        f.setBackground(Color.BLACK);
        f.setSize(800,800);
        panel p=new panel();
        f.add(p);
        Thread t=new Thread(p);  //添加线程
        t.start();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        System.out.println(Thread.activeCount());   //当前线程活跃数目
        //Thread.currentThread().getThreadGroup().list();   //得到调用线程的列表
    }
}

在这里插入图片描述

注意:我们在使用Thread 类的sleep()方法的时候,我们要对其进行异常处理操作,否则会报错的.

(六)、提词器

方法类:

import java.awt.*;
import java.util.Random;

public class panel extends Panel implements Runnable {
    int x=100;
    public void run(){
       while (true){
        x=x+10;
        if(x>1920){
            x=100;
        }
        try {
            Thread.sleep(30);
        }catch (Exception e){
            e.printStackTrace();
        }repaint();
       }
    }
    public void paint(Graphics g) {
        Font f=new Font("黑体",Font.BOLD ,80);
        Color c=new Color(225,215,30);
        g.setColor(c);
        g.setFont(f);
        g.drawString("你",x,250);
        }
}

主类:

import java.sql.SQLOutput;
import java.util.*;
import java.awt.*;
import java.lang.Math;
public class hello  {
    public static void main(String []avgs) {
        Frame f=new Frame();
        f.setTitle("宝马");
        f.setBackground(Color.BLACK);
        f.setSize(1920,1080);
        panel p=new panel();
        f.add(p);
        Thread t=new Thread(p);
        t.start();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
        System.out.println(Thread.activeCount());   //当前线程活跃数目
        //Thread.currentThread().getThreadGroup().list();   //得到调用线程的列表
    }

}

(七)、回弹的小球

在这里插入图片描述

类方法

import javax.swing.*;
import java.awt.*;
import java.util.Random;

public class panel extends Panel implements Runnable {
    int x=100;
    int y=100;
    int att=0;
    public void run(){
     while (true){
        //设置四个姿态:
        //右墙
        if(att==0){
            x++;
            y++;
        }
        //下强
        if(att==1){
            x--;
            y++;
        }if(att==2){//左墙
            x--;
            y--;
        }if(att==3){//上强
            x++;
            y--;
        }
        if(x>733){
            if(att==0){att=1;}
            else{att=2;}
        }
        if(y>711){回弹
            if(att==1){att=2;
            }else{att=3;}
        }
        if(x<0){
            if(att==2){
                att=3;
            }else{
                att=0;
            }
        }
        if(y<0){
            if(att==3){att=0;}
            else{att=1;}
        }
        try {
            Thread.sleep(1);
        }catch (Exception e){
            e.printStackTrace();
        }repaint();
    }}
    public void paint(Graphics g) {
        Color c=new Color(255,0,255);
        g.setColor(c);
        g.fillOval(x,y,50,50);
        }
}

类方法:

import java.sql.SQLOutput;
import java.util.*;
import java.awt.*;
import java.lang.Math;
public class hello  {
    public static void main(String []avgs) {
        Frame f=new Frame();
        f.setTitle("宝马");
        f.setBackground(Color.BLACK);
        f.setSize(800,800);
        panel p=new panel();
        f.add(p);
        Thread t=new Thread(p);
        t.start();
        f.setLocationRelativeTo(null);
        f.setVisible(true);
    }
}

在这里插入图片描述

(八)满天星辰(垂直降落版本)

基本思路:如果要垂直降落的话,我们需要借助一个载体来帮我们储存乱序的300颗星星,首先我们呢可以想到数组的作用。数组可以帮我们用来储存元素的一系列的操作。首先我们要分析这个数组要建立在paint方法的外面因为如果放在里面,在线程的调用的同时我们的数组也会重新更新。我们的而目的是不让数组更新,所以数组必须在类外进行初始化。初始化的时候我们得想到构造函数,利用构造函数进行对数组得第一个300元素进行随机分配。然后在run函数里面对初始化得数组进行高度++程序,从而到达垂直降落的效果。
类方法:

import javax.swing.*;
import java.awt.*;
import java.util.Random;
public class panel extends Panel implements Runnable  {

    int []m=new int[300];
    int []n=new int[300];
    public panel(){   //利用构造函数进行初始化前300

        for(int i=0;i<300;i++){
            Random r=new Random();
            int m1=r.nextInt(1920)+1;
            int n1=r.nextInt(1080)+1;
            m[i]=m1;n[i]=n1;
        }
    }
    public void run(){
        while(true){
            for(int i=0;i<300;i++) {
                n[i]++;
                if(n[i]==1080){
                    n[i]=0;
                }
            }
            try {
                Thread.sleep(10);
            } catch (Exception e) {
                throw new RuntimeException(e);
            }repaint();
        }
    }
    public void paint(Graphics g){
                Font f1 = new Font("黑体", Font.BOLD, 30);
                Random r = new Random();
                int m1=r.nextInt(255)+1;
                int m2=r.nextInt(255)+1;
                int m3=r.nextInt(255)+1;
                g.setFont(f1);
                Color c = new Color(m1, m2, m3);
                g.setColor(c);
                for (int i=0;i<300;i++) {   //绘制300个星星
                g.drawString("*", m[i], n[i]);
            }

    }
}

主方法:

import java.sql.SQLOutput;
import java.util.*;
import java.awt.*;
import java.lang.Math;
public class hello {
    public static void main(String[] avgs) {
    Frame f=new Frame("小球的撞击效果示范图");
    f.setSize(1920,1080);
    f.setBackground(Color.black);
    f.setLocationRelativeTo(null);
    panel p=new panel();
    f.add(p);
    Thread t=new Thread(p);
    t.start();
    f.setVisible(true);
    }
}

在这里插入图片描述