`
_kudy
  • 浏览: 16574 次
  • 性别: Icon_minigender_1
  • 来自: 广州
社区版块
存档分类
最新评论

javase_19(多线程)

 
阅读更多

进程:

进程是具有一定独立功能的程序关于某个数据集合上的一次运动.

 

线程:

线程是进程里面的一个实体,CPU调度或分派的基本单位

 

进程与线程之间的区别:

总而言之,一个进程里面可以有多个线程,但是一个进程至少有一个线程

 

多线程存在的意义:

程序允许有多个线程并发,提供程序的运行的效率   

 

线程的创建方式:

new Thread().start();

 

 

 

 

 

 

多线程的应用:

Sun公司为我们提供了Thread类来实现线程

通过new Thread()来创建一个线程对象.

定义一个类继承Thread,子类就有了线程的功能

创建Thread类的子类的对象,也可以创建一个线程.

 

线程的启用:

Thread类定义了run()方法,用于启动当前的线程

在启用当前的线程的时候,虚拟机会自动调用于run()方法

 

线程的其他方法:

sleep:使线程进入到睡眠的状态,需要唤醒的时间,会抛异常

setDaemon:将当前的线程设置为一个后台的线程,但主线程结束,它也会跟着结束

Join:合并一个线程,会抛出异常-->合并进来,join被谁调用,谁就执行.

currentThread:获取当前运行的线程.

 

 

 

package com.javami.kudy.DemoThread;

public class ThreadTest {
    
    public static void main(String[]args)
    {
        int num = 0;
        MyThread mt = new MyThread();
        //为当前的线程起名字
        mt.setName("kudy-0");
        mt.setDaemon(true); //设置为后台线程,但主线程执行完毕.后台线程也会跟着退出
        mt.start();
        //一个进程至少有一个主线程
        while(true)    
        {
            if(num++>10)
                break;
            try{mt.join();}catch(Exception e){e.printStackTrace();}
            try{Thread.sleep(10);}catch(Exception e){e.printStackTrace();}
            System.out.println(Thread.currentThread().getName()+"Main()");
        }
        
    }
}


class MyThread extends Thread
{
    @Override
    public void run()
    {
        while(true)
        {
            //获取当前线程
            try{Thread.sleep(10);}catch(Exception e){e.printStackTrace();}
            System.out.println(Thread.currentThread().getName()+" run()");
        }
    }
}

 

创建线程的方式二:

 

实现Runnable接口

子类覆盖父类中的run()犯法

通过Thread类创建线程,并且实现了Runnable接口中的子类

对象作为参数传递给Thread类型类的构造函数

 

这样做有什么好处:

线程开了,并且只是处理一个对象.用到了组合模式

 

为什么需要用到同步代码块或者同步函数:

 

由于程序在执行的时候,会出现线程不安全的问题,所以我们需要用到同步函数或者同步代码块.

导致线程不安全的注意问题:

 

1.多个线程随机访问延时

2.线程随机性

 

同步代码块:

Synchronized(对象)  //锁旗标 0开 1

{

需要同步的代码;

}

同步代码可以解决安全的问题根本原因在于对象上面,该对象如同锁的功能.

 

同步函数:

在函数上面加上synchronized修饰即可.

Public synchronized void sale()

{

//同步代码块使用的锁是this这个锁

}

死锁:

发生在相互调用的情况下,一个同步函数里要用到和同步代码块相同的锁,同步代码块又去调用函数,就用到函数的锁,两者都会锁死,发生死锁的问题.

 

package com.javami.kudy.DemoThread;
 
 public class TicketsSale {
 
     /**
      * @param args
      * 多线程售票:同时开启4个线程售票
      * 
      * 线程安全问题在理想的状态下,不容易出现,但一旦出现就是对软件的影响是非常之大
      * Thread-1  -1
        Thread-0  0
        Thread-3  1
        ----↓
        同步代码块
        与同步函数:
        
      */
     public static void main(String[] args) {
         SaleThread st = new SaleThread();
         
         //4个进程产生
         new Thread(st).start();
         new Thread(st).start();
         new Thread(st).start();
         new Thread(st).start();
     }
 }
 
 class SaleThread implements Runnable
 {
     String lock = ""; //锁期标
     private int tickets = 10; //10张车票
     @Override
     public void run()
     {
         
         while(true)  // 0 1 2 3 等待我执行完毕别的线程才去抢
         {
             synchronized(lock)
             {
             if(tickets<1)
                 break;
             try{Thread.sleep(10);}catch(Exception e){e.printStackTrace();}
             System.out.println(Thread.currentThread().getName()+"  "+tickets--);
             }
         }
     }
 }

 

同步的特点:

 

1.同步需要两个或者两个以上的线程.

2.多个线程使用的是同一把锁

3.为满足这两个条件,不能称其为同步.

 

同步的弊端:

 

1.当线程相当多的时候,因为每个线程都会去判断同步上的锁.这是很消耗资源的,判断该锁是否被锁上.如果锁上.需要等锁上的开了才可以互相抢进去.

无形中可以减低了程序运行的效率.

 

package com.javami.kudy.DemoThread;
 
 public class TicketsSale1 {
     /*
      * 使用同步函数与同步代码块来实现4个线程
      */
     public static void main(String[]args)
     {
         SaleThread1 st = new SaleThread1();
         new Thread(st).start();
         new Thread(st).start();
         st.lock = "ok";
         try{Thread.sleep(10);}catch(Exception e){e.printStackTrace();}
         new Thread(st).start();
         new Thread(st).start();
     }
 }
 
 class SaleThread1 implements Runnable
 {
     String lock = " ";
     private int num = 100;
     public void run()
     {
         if(lock.equals("ok"))
         {
             while(true)
             {
                 sale();
             }
         }else
         {
             while(true)
             {
                 synchronized (this) {
                     if(num<1)
                         return;
                     System.out.println(Thread.currentThread().getName()+"else"+num--);
                 }
             }
         }
     }
     
     
     private synchronized void sale() {
             if(num<1)
                 return;
             System.out.println(Thread.currentThread().getName()+"if"+num--);
     }
 }

  

线程间的通信:

 

两个线程之间可以相互的通信

一个线程可以通过wait方法等待,这时CPU会让给别程

通过进行等待的线程需要其他线程调用notify()方法唤醒.

package com.javami.kudy.DemoThread;
 
 /*
  * 通信必须要在同步函数里面去解决的
  */
 class SQL
 {
     public String name;
     public String sex;
     public boolean  b = false;
 }
 class DBA implements Runnable
 {
     SQL sql ;
     public DBA(SQL sql)
     {
         this.sql = sql;
     }
     public void run()
     {
         int num = 0;
         while(true)
         {
             synchronized (sql) {
             if(sql.b) //为真.我等待,让给别的进程~
                 try{sql.wait();}catch (Exception e) {e.printStackTrace();}
             if(num ==0)
             {
                 sql.name = "小细";
                 sql.sex = "男";
             }else
             {
                 sql.name = "美怡";
                 sql.sex = "女";
             }
                 num = (num+1)%2;  //实现了来回打印
                 sql.b = true;
                 sql.notify(); //等待完毕需要把你唤醒~
             }
         }
     }
 }
 
 /*
  * 编码员
  */
 class Coder implements Runnable
 {
     SQL sql ;
     public Coder(SQL sql)
     {
         this.sql = sql;
     }
     public void run()
     {
         while(true)
         {
             synchronized (sql) {
                 if(!sql.b) //如果为假-->我等待
                 try{sql.wait();}catch(Exception e){e.printStackTrace();}
                 System.out.print(sql.name+" ");
                 System.out.println(sql.sex+" ");
                 sql.b = false; //标记为假~~并且把这个进程唤醒
                 sql.notify();
             }
         }
     }
 }
 public class SqlThread {
 
     /**
      * 模仿数据库的操作,实现边读取,边打印
      */
     public static void main(String[] args) {
             SQL sql = new SQL();
             DBA dba = new DBA(sql);
             Coder cr = new Coder(sql);
             new Thread(dba).start();  //一个线程交换位置
             new Thread(cr).start(); //另外一个线程马上就打印出来
     }
 
 }

 

思考:

wait(),notify(),notifyAll(),用来操作线程为什么定义在了Object类中?

wait(),sleep()有什么区别?

Wait():假设我同步代码块抢到啦.我执行wait()方法,就会让该线程等待.让别的线程执行.

Notiyf():唤醒等待中的线程-->下一个

notiyfyAll():  唤醒在此对象监视器上等待的所有线程。

Sleep():这个是去睡觉去啦~~~不需要你唤醒的,这家伙是自然醒.

使用1.5lockcondition解决存和取之间的通信问题

 

 

package com.javami.kudy.DemoThread;

import java.util.concurrent.locks.Condition;
import java.util.concurrent.locks.Lock;
import java.util.concurrent.locks.ReentrantLock;

/*
 * 锁必须要一样,才能称得上同步
 */
class MyArray1
{
	private int[] arr = new int[10];
	private int savePos = 0;
	private int getPos = 0;
	private Lock lock = new ReentrantLock(); //创建一个锁
	private int count = 0;
	private Condition isFull = lock.newCondition(); //返回一个通信对象
	private Condition isEmpty = lock.newCondition();//返回的地址一样
	
	public void add(int num) throws InterruptedException
	{
		//但我执行慢的时候.我这个锁会开.开的时候.一看count==10等待..又抢,如果是你.你就等待.否则就是get  但是执行完毕一定要把当前的线程唤醒
		try
		{
			lock.lock();//开锁
			while(count==10)
				isFull.await();//if等于10了,你就必须等待
			if(savePos==10)
				savePos = 0;
			arr[savePos++] = num;
			count++;
		}finally
		{
			isEmpty.signal();//唤醒
			lock.unlock();
		}
	}
	
	public int get() throws InterruptedException
	{
		try
		{
			lock.lock(); //开锁
			while(count==0)
				isEmpty.await();//等待
			if(getPos==10)
				getPos = 0;
			count--; //不-- ~?  数组问题
			return arr[getPos++];
		}finally
		{
			isFull.signal();//等待的哥们.我去叫醒你啦~~
			lock.unlock();//开锁
		}
	}
}
public class ArrayThreadDemo {
	static int num = 1;
	public static void main(String[]args)
	{
		final MyArray1 ma = new MyArray1();
		new Thread(new Runnable(){
			@Override
			public void run() {
				for(int i=0; i<30; i++)
				{
					try {
						ma.add(num++);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			
		}).start();
		new Thread(new Runnable(){

			@Override
			public void run() {
				for(int i=0; i<30; i++)
				{
					try {
						System.out.println(ma.get());
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			
		}).start();
		new Thread(new Runnable(){
			@Override
			public void run() {
				for(int i=0; i<30; i++)
				{
					try {
						ma.add(num++);
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			
		}).start();
		new Thread(new Runnable(){

			@Override
			public void run() {
				for(int i=0; i<30; i++)
				{
					try {
						System.out.println(ma.get());
					} catch (InterruptedException e) {
						// TODO Auto-generated catch block
						e.printStackTrace();
					}
				}
			}
			
		}).start();

	}
}


今天的知识点回顾:

总体来说:但是今天的精神很好..最后面的一道题目要多加练习
第二: 同步函数是:必须执行完才执行到你,但是同步完毕后不保证以后线程(抢)线程的情况.所以我们又用到 wait() 等待  唤醒(下一个的概念)
但是前提是同步函数里面使用.并且是同一把锁.注意锁的概念.程序要多敲-->后面理解毕竟不是很好.

 

分享到:
评论

相关推荐

    JavaSE基础入门视频教程33天之(26) part2

    在“day26_19(多线程)线程的状态图.avi”中,会详细讲解线程的五种状态:新建、就绪、运行、阻塞和终止。理解这些状态有助于开发者更有效地管理线程的生命周期。 接着,“day26_21(多线程)JDK5实现线程池.avi”将...

    javaSE学习用的PPT

    9. **18.JAVA多线程.ppt**:多线程是Java的重要特性,用于实现并发和异步处理。PPT可能解释了线程的创建、同步、互斥锁、守护线程等相关概念。 10. **19JAVA GUI.ppt**:这部分可能扩展了AWT,讲解Swing库,它是...

    JavaSE基础面试题.docx

    32. **多线程死锁**:两个或更多线程相互等待对方释放资源,导致无法继续执行的状态。 33. **线程池理解**:线程池预先创建一定数量的线程,复用已有线程,提高系统效率,避免频繁创建销毁线程的开销。 34. **常用...

    JavaSE笔试问答题.docx

    JavaSE是Java的标准版,包含了Java的核心特性,如基本数据类型、类、接口、异常处理、多线程等。这份18年的JavaSE面试宝典涵盖了广泛的Java基础知识和进阶概念,以下是其中部分问题的详细解答: 1. 当Class实现...

    JavaSE基础入门视频教程33天之(19) part2

    Vector类与ArrayList类似,但它是线程安全的,适合多线程环境。而Set接口,如其名,强调的是无序且唯一性,它的实现类如HashSet和TreeSet,分别以哈希表和红黑树作为底层数据结构,提供了不同的性能特性。 通过这五...

    JavaSE笔试程序题(20180307)

    JavaSE笔试程序题涵盖了许多核心Java编程概念,包括设计模式、数据结构、算法、多线程、I/O操作以及字符串处理等。以下是这些题目中涉及的知识点详解: 1. **Singleton模式**:确保一个类只有一个实例,常用于配置...

    javaSE代码实例

    第16章 多线程——Java中的并发协作 343 16.1 线程的基本知识 343 16.1.1 多线程编程的意义 343 16.1.2 定义自己的线程 344 16.1.3 创建线程对象 345 16.1.4 启动线程 347 16.1.5 同时使用多个线程 ...

    狂神笔记,b站狂神说课程笔记大全(最新)

    11、JavaSE:多线程 12、JavaSE:网络编程 13、JavaSE:Gui编程 14、JavaSE:注解和反射 15、MySQL和JDBC 16、前端:Html5 17、前端:CSS3 18、前端:JavaScript、jQuery 19、JavaWeb 20、MyBatis 21、Spring 22、...

    JavaSE Notes.doc

    这份"JavaSE Notes.doc"笔记涵盖了从基础到进阶的多个Java SE核心概念。以下是对笔记内容的详细解析: ### 前言 前言部分可能介绍了学习JavaSE的重要性,包括它的广泛应用、就业市场的需求以及学习路线图,帮助读者...

    尚硅谷JAVASE基础课件

    19. **多线程**:学习创建和管理线程,线程同步和通信机制,如synchronized关键字,wait()、notify()和notifyAll()方法。 20. **反射**:理解反射机制,动态加载类,创建对象,调用方法,以及获取类信息。 以上...

    JAVASE阶段经典笔试题20道

    19. **字符串连接**: - 当多个字符串常量通过"+"连接时,编译器会在编译阶段优化成一个字符串,因此只创建一个对象。 20. **sleep()与wait()**: - `sleep()`:使当前线程休眠指定时间,不会释放锁,只是让出CPU...

    狂神说上课笔记未删减 Java基础到技术升级

    11、JavaSE:多线程 12、JavaSE:网络编程 13、JavaSE:Gui编程 14、JavaSE:注解和反射 15、MySQL和JDBC 16、前端:Html5 17、前端:CSS3 18、前端:JavaScript、jQuery 19、JavaWeb 20、MyBatis 21、...

    JavaSE练习题.pdf

    - Java支持多线程机制,增强了程序的并发能力。 3. **Java语言特点** - 自动垃圾回收机制:Java的内存管理由垃圾回收器自动进行,程序员无需手动释放内存。 - 面向过程的编程语言:这不是Java的特点,Java是面向...

    0基础大数据实战 视频教程 下载 因为太大存百度云盘1.zip

    │ day21_多线程与网络编程.rar │ day22_反射.rar │ day23_MySQL1.rar │ day24_MySQL2.rar │ day25_MySQL3.rar ├─9 │ 1、预测结果转换.wmv │ 2、准确率、精确率、召回率.wmv │ 3、准确率、精确...

    0基础大数据实战 视频教程 下载 因为太大存百度云盘2.zip

    │ day21_多线程与网络编程.rar │ day22_反射.rar │ day23_MySQL1.rar │ day24_MySQL2.rar │ day25_MySQL3.rar ├─9 │ 1、预测结果转换.wmv │ 2、准确率、精确率、召回率.wmv │ 3、准确率、精确...

    0基础大数据实战 视频教程 下载 因为太大存百度云盘3.zip

    │ day21_多线程与网络编程.rar │ day22_反射.rar │ day23_MySQL1.rar │ day24_MySQL2.rar │ day25_MySQL3.rar ├─9 │ 1、预测结果转换.wmv │ 2、准确率、精确率、召回率.wmv │ 3、准确率、精确...

    0基础大数据实战 视频教程 下载 因为太大存百度云盘4.zip

    │ day21_多线程与网络编程.rar │ day22_反射.rar │ day23_MySQL1.rar │ day24_MySQL2.rar │ day25_MySQL3.rar ├─9 │ 1、预测结果转换.wmv │ 2、准确率、精确率、召回率.wmv │ 3、准确率、精确...

    狂神说Java 笔记,java入门,docker ,spring 全家桶,redis , mysql , vue , javascript ,htm5, css

    11、JavaSE:多线程.pdf 12、JavaSE:网络编程.pdf 13、JavaSE:Gui编程.pdf 14、JavaSE:注解和反射.pdf 15、MySQL和JDBC.pdf 16、前端:Html5.pdf 17、前端:CSS3.pdf 18、前端:JavaScript、jQuery.pdf ...

    javase 学习笔记(李巍老师)

    14. **线程**:线程是程序的执行路径,Java提供了Thread类和Runnable接口实现多线程。通过start()方法启动线程,join()使当前线程等待,synchronized关键字实现线程同步。 七、反射与注解 15. **反射**:允许程序在...

    javaSE练习题2及答案.docx

    1. **Java与C语言的比较**:Java语言在性能上可能不如C语言,但它提供了一次编写,到处运行的跨平台特性,而且是一种面向对象的语言,具有内置的多线程机制。选项A指出Java性能比C语言差,这是正确的。 2. **Java...

Global site tag (gtag.js) - Google Analytics