黑马程序员----多线程技术理解

来源:互联网 发布:人工智能工程师 编辑:程序博客网 时间:2024/05/18 00:27

----------Java培训、Android培训、iOS培训、.Net培训、期待与您交流!------------

概念:

进程:是一个正在执行中的程序。每一个进程执行都有一个执行顺序,该顺序是一个执行路径,或者叫一个控制单元。


线程:就是进程中的一个独立的控制单元。线程在控制着进程的执行,一个进程中至少有一个线程。

线程中的两种实现方式
线程的二种创建方式为别为继承Java.lang.Thread和实现Java.lang.Runnable接口
一、继承Thread类
Thread类是Java.lang包中的一个类,从这个类中实例化的对象代表线程,
程序员启动一个新线程需要建立Thread实例。
Thread类中常用的两个构造方法如下:
public Thread(String threadName)
public Thread()
继承Thread类创建线程的语法格式
   public class ThreaTest extend Thread{
     //...........
    
    }
在这个过程中完成线程真正的功能的代码放在类的run()方法中,当一个类继承Thread类后,就可以在该类中覆盖run的方法,将实现该线程功能的代码写入run()方法中,然后同时调用Thread类中的start()方法执行线程,也就是run()方法。

注意:如果start()方法调用一个已经启动的线程,系统将抛出IllegalThreadStateException异常

在项目中创建ThreadTest类,该类继承Thread类方法创建线程 public  class ThreadTest extends Thread{                //指定类继承Thread类        private int count=10;        public void run(){                               //重写run方法         while(true){      System.out.print(count+"");                        //打印count变量      if(--count==0){                                   //使count变量自减,当为0时,退出循环      return;      }    }  }  public static void main (String[] args){  new ThreadTest().start();  }}
二、实现一个接口Runnable
线程都是通过扩展Thread类创建的,如果程序员需要继承其它类并使该程序可以使用线程,就需要使用Runnable接口
实现Runnable接口的语法如下:
public class Thread extends Object implements Runnable

实现Runnable接口的程序会创建一个Thread对象,并将Runnable对象与Thread对象关联,Thread类中有如下两个构造函数
     public Thread(Runnable r)
     public Thread(Runnable r,String name)

实现一个接口Runnable步骤:
1,定义类实现Runnable接口
2,覆盖Runnable接口中的run方法。将线程要运行的代码存放在该run方法中。
3,通过Thread类建立线程对象。
4,将Runnable接口的子类对象作为实际参数传递给Thread类的构造函数。
    为什么要将Runnable接口的子类对象传递给Thread的构造函数。
    因为,自定义的run方法所属的对象是Runnable接口的子类对象。
    所以要让线程去指定指定对象的run方法。就必须明确该run方法所属对象。
5,调用Thread类的start方法开启线程并调用Runnable接口子类的run方法。

在项目中创建SwingAndThread类,该类继承了JFrame类实现图标在标签上滚动的功能import java.awt.*;import java.net.*;import javax.swing.*;public class SwingAndThread extends JFrame {/** *  */private static final long serialVersionUID = 1L;private JLabel jl = new JLabel(); // 声明JLabel对象private static Thread t; // 声明线程对象private int count = 0; // 声明计数变量private Container container = getContentPane(); // 声明容器public SwingAndThread() {setBounds(300, 200, 250, 100); // 绝对定位窗体大小与位置container.setLayout(null); // 使窗体不使用任何布局管理器URL url = SwingAndThread.class.getResource("/1.gif"); // 获取图片的URLIcon icon = new ImageIcon(url); // 实例化一个Iconjl.setIcon(icon); // 将图标放置在标签中 // 设置图片在标签的最左方jl.setHorizontalAlignment(SwingConstants.LEFT);jl.setBounds(10, 10, 200, 50); // 设置标签的位置与大小jl.setOpaque(true);t = new Thread(new Runnable() { // 定义匿名内部类,该类实现Runnable接口public void run() { // 重写run()方法while (count <= 200) { // 设置循环条件 // 将标签的横坐标用变量表示jl.setBounds(count, 10, 200, 50);try {Thread.sleep(1000); // 使线程休眠1000毫秒} catch (Exception e) {e.printStackTrace();}count += 4; // 使横坐标每次增加4if (count == 200) {// 当图标到达标签的最右边,使其回到标签最左边count = 10;}}}});t.start(); // 启动线程container.add(jl); // 将标签添加到容器中setVisible(true); // 使窗体可视// 设置窗体的关闭方式setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);}public static void main(String[] args) {new SwingAndThread(); // 实例化一个SwingAndThread对象}}
线程的同步
单线程程序中,每次只能做一件事,后面的事情要等待前面的事情完成后才可以进行,但是如果使用多线程程序,就会发生抢占资源的问题,所以在多线程编程中,需要防止这些资源访问冲突。Java中提供线程同步机制来放在资源访问冲突
一、线程安全
在实际开发中,使用多线程的情况很多,如银行排号系统、火车站售票系统等。这种多线程的程序通常会发生安全问题
我们以下面的例子来说明问题
在项目中创建ThreadSafeTest类,该类继承Runnable类,主要模拟火车站售票系统public class ThreadSafeTest implements Runnable {int num = 10; // 设置当前总票数public void run() {while (true) {if (num > 0) {try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}System.out.println("tickets" + num--);}}}public static void main(String[] args) {ThreadSafeTest t = new ThreadSafeTest(); // 实例化类对象Thread tA = new Thread(t); // 以该类对象分别实例化4个线程Thread tB = new Thread(t);Thread tC = new Thread(t);Thread tD = new Thread(t);tA.start(); // 分别启动线程tB.start();tC.start();tD.start();}}<span style="color:#FF0000;"> 二、线程同步机制</span>在程序运行的时候出现负值,如何解决这个问题为此我们引入同步机制解决多线程资源冲突问题,在同步机制中通过采用两种方法解决资源冲突问题1、同步块    在Java提供了同步机制,可以有效防止资源冲突同步机制使用synchronized关键字 public class ThreadSafeTest implements Runnable {int num = 10;public void run() {while (true) {synchronized ("") {if (num > 0) {try {Thread.sleep(1000);} catch (Exception e) {e.printStackTrace();}System.out.println("tickets" + --num);}}}}public static void main(String[] args) {ThreadSafeTest t = new ThreadSafeTest();Thread tA = new Thread(t);Thread tB = new Thread(t);Thread tC = new Thread(t);Thread tD = new Thread(t);tA.start();tB.start();tC.start();tD.start();}}



 通过运行打印到最后的票数没有出现负数,这是因为将资源放入在同步块中。这个同步块也被称为临界区,他使用了synchronized关键字建立其语法格式如下
synchronized(Object){
      }

2、同步方法
同步方法就是在方法前面修饰synchronized关键字的方法,语法格式:
synchronized void function(){
修改例子将共享资源操作放置在同步方法中在项目中创建一个类文件在该累赘定义同步方法public synchronized void doit(){   if(num>0){   try{      Thread.sleep(10);  }  catch(Exception e){       e.printStackTrace();   }   System.out.println("ticks"+-----num);}}public void run(){      while(true){  doit(); }}


0 0
原创粉丝点击