`

j2se-------进程与线程

    博客分类:
  • J2SE
阅读更多
多进程:在操作系统中能(同时)运行多个任务(程序)

多线程:在同一应用程序(进程)中有多个顺序流(同时--从宏观上看,从微观上看叫交错执行)执行


windows 是多进程的操作系统,也就是说在同一个时间段内可以打开word编写东西,而且也可以打开暴风影音看电影

所以进程就是:正在运行的程序集合体(在有多线程情况下)。。。。

线程体会: 我们在编写word的时候,经常word会给我们写错的字画上一个小红下划线,那么在这个进程之上 我们可以如入文字,而且word会同时检测错误。

在同一个进程上面并行运行多个东西,他是对进程的进一步划分,所以如果一个进程消失了,那么在他上面的线程就消失了,在多线程任务中所有的程序共享系统资源。

多线程上同时有多个程序在运行。 一个线程对应一个程序哈,所谓程序在执行意思是:程序区段(代码段)正在命令cpu做事情

注意:在Thread源码中的start方法,会调用一个private native void start0();的方法,
而native关键字表示是一个由java调用本机操作系统函数的关键字,在java中,运行java程序调用本机的操作系统的函数以完成特定的功能

这证明:如果现在想要实现多线程,则肯定需要操作系统的支持,因为多线程操作中牵涉到一个抢占cpu的情况,要等待cpu进行调度,那么这一点肯定需要操作系统的底层支持,所以使用了native调用本机的系统函数

Thread和Runnable的区别:
   1。使用Thread类在操作多线程的时候无法达到资源共享的目的,而使用Runnable接口实现的多线程操作可以实现资源共享。。。。只共享实例变量哈,局部变量还是不共享哈
    2。单继承有开发局限,因为你继承了Thread你就不能继承其他的类了

   其原因是,如果使用Thread ,那么多线程的话会要 new出来多个Thread
   而使用Runnable的话   public class MyThread implements Runnable{ int i = 0...}
   MyThread m = new MyThread(); 
   new Thread(m).start();
   new Thread(m).start();
   new Thread(m).start(); //这样同一个类被变成三个线程启动,那么里面的实例变量当然也会被共享  



创建状态: 准备好了一个多线程的对象,Thread t = new Thread();
就绪状态:调用了start()方法,等待cpu进行调度
运行状态: 执行run()方法
阻塞状态: 暂时停止执行,可能将资源交给其他线程使用

就像一个运动员跑不一样,来到跑场(创建),准备跑步(就绪),跑步(运行),摔跤(阻塞)。。
-----------------------------------------------------------------------------------Name
在Thread类中,可以通过getName()方法取得线程名称,可以setName()设置线程名称,
线程的名称一般在启动线程前设置,但也允许为已经允许的线程设置名称,允许两个Thread对象有相同的名称
如果没有设置名称,那么系统会自动分配一个名称

类比: 一个人在出生的时候给了一个名字,但是这个人活到60岁想改名称,这肯定很麻烦,
线程的名字在线程启动之前设置,避免重名



------------------------------------------------------------------------------------
Thread.currentTHread();方法可以取得当前正在运行的线程对象,如果有多个线程的话,那么我们可以写这个代码放到线程之中,就可以把线程相区别
public class MyThread implements Runnable{ int i = 0.;
   public void run(){
       System.out.println(Thread.currentThread().getName());
   }
}

public class Test{
   public static void main(String[] args){
        MyThread m = new MyThread();
        new Thread(m,"我是线程").start(); //创建并就绪线程
        m.run();        //在主方法里面启动线程
   }
}



每当java程序执行的时候,实际上会启动一个JVM,每个JVM实际就是操作系统中启动了一个进程(java.exe),而主方法是以线程的形式启动的,所以当一个java运行的时候至少启动两个线程,一个是主线程,一个垃圾回收期(GC)

t.isLive(); //表示是否t线在start()之后,在destory()之前,就算他是在阻塞状态没得到cpu他也是存活的,如果没start()那么不算存活,类比就是:是否这个运动员在比赛中。。。


t.join();//线程强制运行,当这个方法被调用,那么这个t小子就开始插队到第一个,并告诉cpu,你得先把我的命令全部执行完后,你再去交叉调用别人。。。

public static void main(String[] args){
    MyThread mt = new MyThread();
    Thread t = new Thread(mt);
    t.start();
    for(int i=0;i<50;i++){
        if(i>10){
            try{
               t.join(); //这里是主方法让t小子插队的,也就是我主方法排在t的后面去执行后面的代码,我们可以把这个东西想象成为 加入队列顺序执行,当t执行完成之后再启动并行执行
            }catch(InterruptedException e){
            }
         System.out.println("main"+i);
        }
    }
}


-------------------------------------------------------------------------Thread.sleep(500);

线程休眠 : 那个线程调用这个方法,就相当于那个线程问Thread类要一个床,我们可以把这句话理解为: Thread大主管,请给俺一个床,我睡500毫秒即可,注意他睡醒之后不一定立刻得到cpu哦

------------------------------------------------------------------------t.interrupt(); //打断t的休眠,也就是叫醒t,如果t在睡觉,那么叫醒他的话会发生状态转换,会抛异常,如果t本身没有睡觉,那么叫不叫他都是醒的,这个时候当然不会发送状态转换异常啦



class MyThread implements Runnable{
   public void run(){
       System.out.println("1.进入run()方法");
       try{
           Thread.sleep(1000);
           System.out.println("2,已经完成了休眠");  //try catch的作用是当try里面的东西执行出错了之后由catch里面的代码代替try中的错误代码及其以后的代码执行,所以有了try catch之后,程序报错也和没报错一样
       }catch(InterruptedException e){
            System.out.println("3,休眠被终止");
            return;  //这个意思是如果报错了,那么不执行下面的代码了
       }
       System.out.println("4.run()方法正常结束");
   }
}


public class Test{
   public static void main(String[] args){
       MyThread mt = new MyThread();
       Thread t = new Thread(mt);
       t.start();
       try{
          Thread.sleep(2000);
       }catch(Exception e){
          System.out.println("3,休眠终止了");
        }
        t.interrupt();
   }
}

--------------------------------------------------------------------------后台线程,也就是能够脱离进程的线程

在java中,只要一个程序没有执行完(一个线程在运行),则整个java进程不会消失,所以此时可以设置一个后台线程,这样即使java 进程结束了,此后台线程依然会继续执行
后台线程是为其他的线程提供服务的,又称为守护进程,他牛逼就牛逼在JVM退出了他还会执行,也就是说他是直接脱离JVM的,不归JVM管的东西


------------------------------------------------------------------------

线程的优先级

t1.setPriority(Thread.MIN_PRIORITY) ; //优先级最低 值为1
t2.setPriority(Thread.MAX_PRIORITY) ; //优先级最高  值为5
t3.setPriority(Thread.NORM_PRIORITY) ; //优先级普通,也就是中等,值为10
t1.start();
t2.start();
t3.start();
优先级越高越有可能被先执行,但是也会别抢占哦,只是他的机会多些
注意: main()方法的优先级是 普通优先级。。。

------------------------------------------------------------------------------线程的礼让

Thread.yield(); //和join不同的是,他只是让调用它的线程让出cpu,并不指定让出spu后指定谁来执行


-----------------------------------------------------------------------
同步与死锁

什么情况下需要同步?
条件一:此数据时在线程间共享的数据。
条件二:当共享数据正在被写入的时候可能被另一个线程读到 或者 当共享数据正在被读到的时候可能被另一个线程改写

所以如果共享数据牵涉到被改变的时候就要同步
那么在java中,怎样的数据时共享数据呢?
第一: static标识的数据
第二:一个实现了Runnable接口的类的实例变量,也就是说同一个实例别放到多个线程中。。。看下面代码
第三: 直接传递同一个对象给多个线程,那么这些线程就有对这个对象的共享资格了,可以见下面的生产者和消费者例子
class MyThread implements Runnable{
  private int ticket = 5;
   public void run(){
      for(int i=0;i<100;i++){
         if(ticket > 5){ //这是读取共享数据
           try{
             System.out.println("出售第ticket ="+ticket);
              ticket -- ; //这是改写共享数据
               Thread.sleep(1000);
           }catch(InterruptedException e){}
           
         }
   }
}
public class Test{
   public static void main(String[] args){
       MyThread m = new MyThread();
       Thread t1 = new Thread(m); //把这个东西放入了两个线程中间,显然就会对共享数据进行操作
       Thread t2 = new Thread(m);
        t1.start();
        t2.start();
   }
}

上面的代码会出现被修改的情况。。。。下面改进,使用同步代码块
class MyThread implements Runnable{
  private int ticket = 5;
   public void run(){
      for(int i=0;i<100;i++){
       synchronized(this){ //同步时为了把这一系列的操作当成一个原子操作
         if(ticket > 5){ //这是读取共享数据
              try{
                System.out.println("出售第ticket ="+ticket);
                 ticket -- ; //这是改写共享数据
                  Thread.sleep(1000);
              }catch(InterruptedException e){}
          }//if
       }
   }
}


同步真的安全吗?
过多的同步可能引起死锁
故事: 张三想要李四的画,李四想要张三的书,于是张三对李四说:你把你的画给我,我就给你我的书,李四对张三说:你把你的书给我,我就给你我的画。。。于是。。。死锁出现了

class Zhangsan{
	public void say(){
		System.out.println("张三对李四说:”你给我画,我就给你书“");
	}
	public void get(){
		
		System.out.println("张三得到画了");
	}
}

class Lisi{
	public void say(){
		System.out.println("李四对张三说:”你给我书,我就给你画“");
	}
	public void get(){
		System.out.println("李四得到书了");
	}
}

class ThreadDeadLock implements Runnable{
	private static Zhangsan zs = new Zhangsan();
	private static Lisi ls = new Lisi();
	public boolean isZhangsanFirst = true;
	public void run(){
		if(isZhangsanFirst){
			synchronized (zs) { //不让别的线程来问zs有没有书,因为这里zs,ls都是共享变量
				 zs.say();
				 try{
					 Thread.sleep(500);
				 }catch(InterruptedException e){}
				synchronized(ls){ //不让别的线程去拿李四的书
					zs.get();
				}
			}
		}else{
			synchronized (ls) { 
				 ls.say();
				 try{
					 Thread.sleep(500);
				 }catch(InterruptedException e){}
				synchronized(zs){  //这里告诉我们两层嵌套很容易死锁
					ls.get();
				}
			}
		}
	}
	
	public static void main(String[] args){
		ThreadDeadLock zsFirst = new ThreadDeadLock();
		ThreadDeadLock lsFirst = new ThreadDeadLock();
		zsFirst.isZhangsanFirst = true;
		lsFirst.isZhangsanFirst = false;
		Thread t1 = new Thread(zsFirst);
		Thread t2 = new Thread(lsFirst);
	}
}

下面对synchronized(ls){}来做几点说明
synchronized可以用在方法上,一般不用,因为如果是放在方法上的话,那么默认的锁是这个方法所在类的实例,如果我们对这个类new了两个的话,那么根本锁不住
同理synchronized(ls){}能达到锁的目的,是因为这个ls虽然是new出来的,但是是static的,也就是说只会被new一次
还有一种解决方案是synchronized(ls.getClass()){} 因为ls这个对象的类的字节码只有一份。。。。。
或者根据String对象可以在对象池的原理,还可以这样
synchronized("a"){} 呵呵,玩玩而已啦
总之:我们要保证钥匙只有一份就可以了

分享到:
评论

相关推荐

    J2SE-多线程.ppt

    与进程相比,线程更轻量级,因为它们共享同一进程的内存空间,包括代码段和数据段,这使得线程间的通信和切换更为高效。Java通过`java.lang.Thread`类支持线程操作,当虚拟机启动时,会有一个由主方法定义的主线程...

    J2SE 学习心得(一些常用知识要点)PART1

    7. 进程与线程: - 进程是程序的一次执行实例,拥有独立的内存空间。 - 线程是进程内的执行单元,多个线程可以共享同一进程的资源,同时执行。线程间的同步和互斥是通过 `synchronized` 关键字来控制,以防止数据...

    J2SE面试题 经典

    CGI每次请求都需要重新启动一个进程,而Servlet则可以驻留在内存中,多次请求之间共享相同的实例,减少了资源消耗和启动时间。此外,Servlet支持Java的强大功能,如多线程和对象模型,使其在处理复杂Web应用时更具...

    (java)J2SE_核心技术基础

    Java J2SE(Java Standard Edition)是Java平台的核心部分,主要面向桌面应用和服务器端开发。...结合实例代码,理论与实践相结合,将加速你的学习进程,为后续的Java Web和Java EE开发打下坚实基础。

    java 入门教程课件——j2se

    - **线程**:程序执行的最小单元,一个进程可以包含多个线程。 - **并发执行**:多线程使得程序能同时执行多个任务,提高程序效率。 - **同步控制**:通过`synchronized`关键字防止线程间的竞态条件,确保数据...

    java_diary_18.rar_JFC_swing_反射机制_国际化 java

    Day11:多线程-进程与线程及方法 Day12:线程机制与I/O流的方法 Day13:I/O流的类与编码方式 Day14:优化的I/O流与网络编程 Day15:网络编程与常用类库 Day16:国际化与新特性 Day17:新特性与并发线程 Day18:软件...

    java mulitDownload

    - **线程**:线程是程序执行的最小单位,一个进程可以包含多个线程,它们共享进程资源并独立执行。 - **多线程**:在一个应用程序中同时运行多个线程,能够并发处理任务,提高程序的执行效率。 2. **Java中的多...

    JAVA教程解析Java的多线程机制

    子进程与父进程拥有不同的可执行代码和数据内存空间,而同一进程中多个线程共享数据内存空间,每个线程有自己的执行堆栈和程序执行上下文(Context)。 由于这些区别,线程有时被称为轻型进程(LightWeight Process...

    基于J2SE模拟QQ的聊天源程序

    Socket是网络通信的基本单元,它提供了进程间通信(IPC)的能力,特别是在网络环境中。在Java中,Socket类和ServerSocket类用于实现客户端和服务器之间的连接。客户端通过Socket创建连接到服务器的实例,而服务器端...

    最简单J2ME与J2SE的SOCKET链接例子,一看就懂

    SOCKET是网络编程中的基本组件,它提供了一种进程间通信(IPC)的方式,使得不同设备可以通过网络交换数据。 首先,我们来看J2ME部分。J2ME通常用于移动设备和嵌入式系统,它的网络支持相对较弱,但依然可以使用...

    j2se开发的飞行棋源码

    3. **多线程**: 游戏进程通常需要多线程来实现并发处理,比如同时处理多个玩家的回合,或者在后台执行计时任务(例如自动滚动的骰子动画)。 4. **算法与数据结构**: 游戏逻辑中,如何判断棋子的移动规则,如何处理...

    新版Android开发教程.rar

    � Google 提供了一套 Java 核心包 (J2SE 5,J2SE 6) 的有限子集,尚不承诺遵守 Java 任何 Java 规范 , 可能会造 成J ava 阵营的进一步分裂。 � 现有应用完善度不太够,需要的开发工作量较大。--------------------...

    Android面试复习资料

    - 进程与线程:了解进程间的通信方式,线程的调度策略。 - 内存管理:虚拟内存、堆栈、内存分配与回收。 - 文件系统:理解文件的组织方式,权限管理。 - 并发与同步:熟悉互斥锁、信号量、条件变量等同步原语。 ...

    2021-2022计算机二级等级考试试题及答案No.5394.docx

    进程与线程的区别 - **定义**:进程是系统进行资源分配和调度的基本单位,是应用程序运行的一个实例;线程则是进程内的一个执行单元,是CPU调度和分派的基本单位。 - **地址空间**:进程拥有独立的地址空间,这...

    java 面试题 j2ee j2se各个部分都有

    - **CGI**:每次请求都启动一个新的进程,处理完请求后进程退出,效率较低,但每个请求之间隔离,避免了并发问题。 7. **ArrayList、Vector和LinkedList的比较**: - **ArrayList和Vector**基于数组实现,支持...

    java经典面试题

    - 线程是进程内的执行实体。 2. **死锁的必要条件**: - 互斥条件:至少有一个资源必须处于非共享模式。 - 请求与保持条件:一个已经获得资源的进程可能请求新的资源。 - 不剥夺条件:进程已获得的资源不会被...

    java培训总结

    - **J2EE (Java 2 Platform, Enterprise Edition)**: 面向企业级应用开发的平台,包含了J2SE中的所有功能及更多面向服务端的功能。 - **J2ME (Java 2 Platform, Micro Edition)**: 针对嵌入式设备和移动设备的平台。...

    java面试题库大全

    - **线程与进程**:线程的生命周期,同步与互斥,死锁,线程池的使用。 - **并发工具类**:Semaphore、CountDownLatch、CyclicBarrier、ThreadPoolExecutor等。 - **并发容器**:ConcurrentHashMap、...

    jvm工具、参数调优&调试技巧

    ### JVM工具、参数调优与调试技巧 #### 一、JVM工具 ##### 1. jps:虚拟机进程状况工具 - **简介**:`jps` 是一个用于显示当前运行的所有Java虚拟机进程(JVMs)的简单工具。它会列出每个JVM的PID(进程ID)以及...

Global site tag (gtag.js) - Google Analytics