java基础5

一.多线程

--1,概念
        现有的程序,都是只有一个人在干活(单线程程序)--程序的执行效率低
        为了提高程序的执行效率,我们可以让多个人共同去完成这一个任务(多线程程序)
    --2,进程和线程的区别
        --进程--指的是正在运行的程序,有的程序依赖一个进程,有的程序可以依赖很多进程
        --线程--是操作系统能够调度的最小单位,进程包含线程.
            --一个进程的运行至少依赖一个线程--单线程程序--效率低
            --一个进程的运行依赖多个线程--多线程程序--效率高
    --3,并发和并行的区别
    --4,线程的状态/线程的生命周期
        --刚new出来的线程是新建状态
        --可运行状态,等待CPU的调度
        --运行状态,正式开始执行任务
        --理想状态,线程进入结束状态
        --实际情况里,线程会以各种方式进入阻塞状态.

二.多线程编程
    --1,继承Thread类
        --线程是程序中的执行线程。Java 虚拟机允许应用程序并发地运行多个执行线程
        --创建对象
            Thread() 
                      分配新的 Thread 对象。 
            Thread(Runnable target) 
                      分配新的 Thread 对象。 
            Thread(Runnable target, String name) 
                      分配新的 Thread 对象。 
            Thread(String name) 
                      分配新的 Thread 对象。 
        --常用方法
            static Thread currentThread() 
                      返回对当前正在执行的线程对象的引用。 
            long getId() 
                      返回该线程的标识符。 
            String getName() 
                      返回该线程的名称。 
            void run() 
               如果该线程是使用独立的 Runnable 运行对象构造的,则调用该 Runnable 对象的 run 方法; 
            void setName(String name) 
                      改变线程名称,使之与参数 name 相同。 
            static void sleep(long millis) 
                      在指定的毫秒数内让当前正在执行的线程休眠( 
            void start() 
                      使该线程开始执行;Java 虚拟机调用该线程的 run 方法。 
            void stop() 
                      Thread.stop 来终止线程 
        --测试

package cn.tedu.thread;
			//测试  多线程编程
			public class Test2_Thread {
				public static void main(String[] args) {
					//4,测试--让多线程启动起来
					MyThread t1 = new MyThread();//--新建状态
					MyThread t2 = new MyThread();
					//6,设置线程名称
					t1.setName("灭霸");
					t2.setName("猪猪侠");
					//5,启动线程!!!
					t1.start();//--可运行状态--等待CPU调度
					t2.start();
			//		t1.run();//把业务当做普通的方式执行.没有多线程(抢占)效果
			//		t2.run();
				}
			}
			//1,模拟多线程编程--extends Thread
			class MyThread extends Thread{
				//2,把所有业务,写在重写的run()里
				@Override
				public void run() {//--运行状态
					for (int i = 0; i < 100; i++) {
						//3,getName()线程名称 Thread-0  Thread-1 --getId()线程标志
						System.out.println(getId() + super.getName()+"==="+i);
					}
				}//--结束状态
			}


    --2,实现Runnable接口
        --Runnable 接口应该由那些打算通过某一线程执行其实例的类来实现。类必须定义一个称为 run 的无参数方法。
        --常用方法
            void run() 
                  使用实现接口 Runnable 的对象创建一个线程时,启动该线程将导致在独立执行的线                程中调用对象的 run 方法。 
        --测试

package cn.tedu.thread;
			//测试 Runnable
			public class Test3_Runnable {
				public static void main(String[] args) {
					//5,测试--让线程启动起来
					MyRunnable target = new MyRunnable();
					Thread t1 = new Thread(target);//绑定接口实现类和Thread的关系
					//6,启动线程
					t1.start();
					//如何模拟多线程?
					Thread t2 = new Thread(target);
					t2.start();
				}
			}
			//1,模拟多线程编程--implements Runnable
			class MyRunnable implements Runnable{
			//2,实现了Runnable接口,就要把接口里的所有抽象方法都重写,否则就包含着抽象方法是一个抽象类
				//3,在多线程编程中,需要把所有的业务统统放在run()里
				@Override
				public void run() {
					for (int i = 0; i < 100; i++) {
						//4,打印100次线程名称
			//Thread类里的静态currentThread()返回当前正在执行任务的线程对象的引用
						System.out.println(Thread.currentThread().getName()+"==="+i);
					}
				}
			}

--同步锁
    --1,概述
        把有可能出现问题的代码包起来,一次只让一个线程执行。通过sychronized关键字实现同            步。当多个对象操作共享数据时,可以使用同步锁解决线程安全问题。
    --2,语法:
        --使用关键字synchronized表示同步.使多个线程需要排队访问共享资源,而不是发生抢占现象.
        --实现了同步后,好处是:共享数据安全了.坏处是:效率低了.--牺牲了效率,实现了安全.
        --synchronized可以修饰方法,也可以修饰代码块.
        --同步方法--使用的锁对象是this
            synchronized public void eat(){}
        --同步代码块--锁对象可以任意
            synchronized(对象){
                需要同步的代码;
            }
        --以后的数据有没有多线程的数据安全隐患???--多线程编程中--有多条语句操作了共享数据
            

--implements Runnable
			package cn.tedu.thread;
			//解决 线程安全隐患
			public class Test1_Lock {
			    public static void main(String[] args) {
			        //4,测试
			        MyTickets2 target = new MyTickets2();
			        Thread t1 = new Thread(target);
			        Thread t2 = new Thread(target);
			        Thread t3 = new Thread(target);
			        Thread t4 = new Thread(target);
			        t1.start();
			        t2.start();
			        t3.start();
			        t4.start();
			    }
			}
			class MyTickets2 implements Runnable{
			    //需求:让四个窗口,一起卖出100张票
			    int tickets = 100 ;
			    Object obj = new Object();
			    String s = "jack";
			    //目前程序中,由于在多线程编程中,出现了多个线程抢占资源而造成的数据错乱.
			    //加锁来解决数据安全隐患问题.考虑以下两个问题:
			    //1,锁的位置:把会有问题的代码锁起来,从问题源头开始,到结束为止,都包起来
			    //2,锁的对象:代码块里使用锁,需要考虑锁对象是谁?可以是任意对象,只要是同一个对象就行
			    //3,同步锁也可以直接锁方法,默认是用的锁对象是this
			    //4,如果共享资源是 一个 静态资源,锁对象必须是 类名.class!!!
			//  synchronized public void run() {
			    @Override
			    public void run() {
			        while (true) {
			//            synchronized (new Object()) {//还有问题,四个线程就产生了4个对象!!
			//            synchronized (obj) {//从头到尾都是只有一个对象!!!
			//            synchronized (s) {//从头到尾都是只有一个对象!!!
			            synchronized (this) {//从头到尾都是只有一个对象!!!
			                if (tickets > 0) {
			                    try {
			                        Thread.sleep(10);
			                    } catch (InterruptedException e) {
			                        e.printStackTrace();
			                    }
			                    //3,打印线程名称--Thread.currentThread()
			                    System.out.println(Thread.currentThread().getName() + "==" + tickets--);
			                } else {
			                    break;//合理的出口!!
			                }
			            }
			        }
			    }
			}

--extends Thread

package cn.tedu.thread;
			//模拟多线程售票  -- 继承Thread
			public class Test4_Tickets {
				public static void main(String[] args) {
					//4,启动线程
					MyTickets t1 = new MyTickets();
					MyTickets t2 = new MyTickets();
					MyTickets t3 = new MyTickets();
					MyTickets t4 = new MyTickets();
					t1.start();
					t2.start();
					t3.start();
					t4.start();
					//--问题1:总共需要卖出100张票,但是,现在却卖出了400张票.为什么?
					//成员变量tickets,每次实例化时,都会跟着对象初始化一次.4个对象就各自拥有一个tickets,总共变成了400张
					//--问题1的解决方案:把共享资源tickets加static修饰,变成全局唯一全局共享
					//目前来看,程序中的4个线程完美的配合着卖了100张票.
					//但是,数据最终有没有安全隐患--让程序休眠一会儿
				}
			}
			//1,创建多线程类-extends Thread
			class MyTickets extends Thread{
				//--需求:让四个窗口,一起卖出100张票
				static int tickets = 100 ;//定义变量,记录票数
				//2,开始卖票--把业务放入run()
				@Override
				public void run() {
					//一直卖票,卖完结束
					while(true) {//死循环----配置设置好出口!!
						//如果共享资源是 一个 静态资源,锁对象必须是 类名.class!!!
						synchronized (MyTickets.class) {
							if(tickets>0) {
								//!!! 5,验证多线程中,数据是否安全,都要接受这次考验
								//问题2: 超卖: 卖出了0号票,甚至-1号票
								//问题3: 重卖: 同一张票卖给了好几个人
								try {
									Thread.sleep(10);
								} catch (InterruptedException e) {
									e.printStackTrace();
								}
								//3,打印线程名称
								System.out.println(getName()+"===="+tickets--);
							}else {
								break;//合理的出口!!
							}	
						}
					}
				}
			}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

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

余额充值