`

单线程与多线程

    博客分类:
  • j2se
 
阅读更多

 

单线程:按照程序的代码顺序依次执行  
多线程:每次运行结果都不一样
    1.程序:计算机语言的指令集合
    2.进程:正在执行的程序
    3.线程:进程中某个被执行的片段,cup会在不同的线程之间切换,线程是程序执行的最小单位(程序运行要内存,把程序加载到内存,还要cpu,cpu要进行计算)

第一(面试):实现多线程:构造函数默认调用了父类无参的构造
    1.继承Thread(线程),Thread封装的是程序中的某个片段,因此别的类继承他以后,也能达到这个目的(多线程的目的)
    2.重写run方法,在run方法中写的是多个线程都具备的功能(想要达到多线程效果的方法写入run方法中)run方法的功能是实现多线程
    3.start(启动线程)方法,用这个方法以后,jvm会自动调用run方法
第二(面试):第二种实现方式:调用了带一个或者带两个的参数的构造函数
   由于Thread是runnable接口的实现类,因此我的类实现runnable接口也能实现多线程(该接口中只有一个方法run,因此用接口的时候一般需要在main方法中引入Thread对象)
     1.实现runnable接口
     2.重写run方法
     3.创建Thread对象(查线程池)
     3.调用Thread带参构造。用我的类的对象创建线程,线程启动的时候自动调用run方法(thread t1=new thread(u1))

第三(面试):线程安全(线程同步):线程切换具有随机性,有时候线程正在执行一半就切换了,这样就不同步了。
      临界区资源:多个线程共享的资源(一段代码,数据),线程同步就是对临界区资源进行保护。
              对于临界区资源必须保证多线程对临界区资源的执行结果和单线程是一直的(线程同步)
    线程同步的原理:给临界区资源加锁,利用的是java中(引用类型)对象的锁
    1.实现线程同步:使用同步代码块 :synchronized:同步(加锁),退出大括号以后锁就打开了。同步以后并发性降低了。
       synchronized(“hello”),其中hello就是对象(字符串就是引用类型的对象),而且就有这一个对象(只有他有钥匙,能开锁)
    2.实现线程同步:使用同步方法 :把我自己的方法用synchronized修饰,相当于给整个方法加锁。然后将这个方法写入run方法中去执行线程。
        方法中的synchronized调用的相当于是this,this表示每一个对象,我new过几次现在就有几个对象(有多个钥匙了),因为不能实现同步。
        一个实现类的对象封装多个线程。
3.Thread.currentThread()是返回当前线程对象,这是个静态方法。。Thread.currentThread().getName()是得到当前线程的名字


注释:同步代码块能够保证本次循环的线程安全
      同步方法能够保证整个循环的线程安全
run方法实现多线程的时候不管是否同步,如果想同步,就要程序员使用同步代码块或者同步方法


第四:例题:四个售票窗口(可以同时卖票,因此是多线程),一个票池(共享的,临界区资源)
对于多线程,是用继承父类还是用实现接口?
答:由于继承只能是单继承(继承资源是有限的),所以一般用接口实现
   如果需要多个线程共享某个资源,就用实现接口的方法实现多线程,因为可以使用同步方法进行同步。(如果用继承的话,就不能y用同步方法了,因为继承会产生多个对象,同步方法需要this)
出现的个数比想象的多,是因为有的线程判断成功了,只是没执行,下次在执行的时候就不会判断了(因为判断过了)


第五:线程的优先级:得到线程优先级getPriority,返回值是个整数(常量),最小优先级是1,最大是10,默认优先级是5。数字越大优先级又高,高优先级获得的线程运行的几率,不是绝对的
 设置(更改)线程优先级:setPriority(Thread.MAx...)
第六:线程的状态(面试会考):
声明周期:
被创键,start,运行态,wait,等待态,notify,唤醒态
                       ,阻塞态(死锁),阻塞态的:例如TCP协议中的accecp方法,一个监听器,开启之后就是阻塞状态,当客户端有请求来的时候变成运行态
                         消亡


两个人针对一个账号,因为属性需要共享,因此用接口,(因为用接口,在创建对象的时候只需创建一个)

 

 

 

 第二:代码实现

1.调用带一个参数的构造函数

package lianxi.Runnable;
/**
 *以实现Runnable接口的方式实现线程
 */
public class runnableTest1 implements Runnable{
 private String name;
 private String role;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getRole() {
  return role;
 }
 public void setRole(String role) {
  this.role = role;
 }
 public runnableTest1() {
  super();
 }
 public runnableTest1(String name, String role) {
  super();
  this.name = name;
  this.role = role;
 }
  public void move(){
     for(int i=0;i<10;i++){
      System.out.println(this.name+"移动了"+i+"米");
     }
    }
 @Override
 public void run() {//此时相当于三个线程共同用这个run方法
  move();
  
 }
 
 public static void main(String[] args) {
  runnableTest1 r1=new runnableTest1("张三","警察");
  runnableTest1 r2=new runnableTest1("lisa","警察");
  runnableTest1 r3=new runnableTest1("拉搜救","土匪");
  Thread th1=new Thread(r1);//创建线程,这是调用线程带一个参数的构造函数
  Thread th2=new Thread(r2);
  Thread th3=new Thread(r3);
  th1.start();
  th2.start();
  th3.start();
 }
}

 

2.调用带两个参数的构造函数

package lianxi.Runnable;

public class runnableTest2 implements Runnable{
 private String name;
 private String role;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getRole() {
  return role;
 }
 public void setRole(String role) {
  this.role = role;
 }
 public runnableTest2() {
  super();
 }
 public runnableTest2(String name, String role) {
  super();
  this.name = name;
  this.role = role;
 }
 /**  当for循环中的内容不止一句的时候,由于线程的时间片轮转机制,经常会遇到当前线程还没有完成一个完整的for循环,
  *   就转换成其他的线程开始执行这个方法了。也就是说我的这个线程刚执行一半,就轮到其他线程了,为了解决这个问题,就
  *   出现了线程同步(安全)的概念,线程同步分成两个内容,一是方法同步,一个是代码块同步。提高了线程安全,缺降低了线程的并发性
  *   不管是代码块同步还是方法同步,synchronized加锁(同步)的时候都需要一个对象。
  *  
  *  @方法的作用:线程中的同步方法。这里是把方法同步(加锁)了,因此只有这个线程执行完这个方法(完成整个for循环)才会轮到下一个线程。
  *          synchronized在方法同步中需要一个对象,这个对象默认就是this,因此要保证main方法中只创建一次对象,
  *           一个对象创建多个线程,就要用到线程构造方法中的两个参数的构造方法
  *  @作者:褚永也
  *  @日期:2014-7-17 下午2:56:35
  *  @返回值类型:void
  */
  public synchronized void move(){//同步(加锁)方法,这里默认调用的是this对象
     for(int i=0;i<10;i++){
      System.out.println(Thread.currentThread().getName()+" 射击第"+i+"发子弹.....");//得到当前线程的名字
      System.out.println(Thread.currentThread().getName()+" 第"+i+"发子弹,击中目标.");
     }
    }
 @Override
 public void run() {//此时相当于三个线程共同用这个run方法
  move();
  
 }
 public static void main(String[] args) {
  runnableTest2 r = new runnableTest2("张三","警察");//保证了只有一个对象
  Thread t1 = new Thread(r,"线程1");//调用线程的两个参数的构造方法。。。一个对象创建多个线程
  Thread t2 = new Thread(r,"线程2");
  Thread t3 = new Thread(r,"线程3");
  Thread t4 = new Thread(r,"线程4");
  Thread t5 = new Thread(r,"线程5");
  Thread t6 = new Thread(r,"线程6");
  t1.start();
  t2.start();
  t3.start();
  t4.start();
  t5.start();
  t6.start();
  
  
 }
}

 

3.

package lianxi.Runnable;

public class runnableTest3 implements Runnable{
 private String name;
 private String role;
 public String getName() {
  return name;
 }
 public void setName(String name) {
  this.name = name;
 }
 public String getRole() {
  return role;
 }
 public void setRole(String role) {
  this.role = role;
 }
 public runnableTest3() {
  super();
 }
 public runnableTest3(String name, String role) {
  super();
  this.name = name;
  this.role = role;
 }
 /** 当for循环中的内容不止一句的时候,由于线程的时间片轮转机制,经常会遇到当前线程还没有完成一个完整的for循环,
  *   就转换成其他的线程开始执行这个方法了。也就是说我的这个线程刚执行一半,就轮到其他线程了,为了解决这个问题,就
  *   出现了线程同步的概念,线程同步分成两个内容,一是方法同步,一个是代码块同步。提高了线程安全,缺降低了线程的并发性
  * 不管是代码块同步还是方法同步,synchronized加锁(同步)的时候都需要一个对象。
  *
  *  @方法的作用:线程中的同步代码块。代码块同步(加锁),只是本次循环会同步,下次循环就是其他线程执行了。
  *      因此代码块同步的并发性比方法同步要大。synchronized需要一个对象(引用类型的),这里给synchronized
  *      一个字符串类型的变量
  *  @作者:褚永也
  *  @日期:2014-7-17 下午3:08:03
  *  @返回值类型:void
  */
  public  void move(){
     for(int i=0;i<10;i++){
      synchronized ("a") {
       System.out.println(Thread.currentThread().getName()+" 射击第"+i+"发子弹.....");
       System.out.println(Thread.currentThread().getName()+" 第"+i+"发子弹,击中目标.");
   }
     
     }
    }
 
  public void run(){
   this.move();
  }
  public static void main(String[] args) {
   runnableTest3 r1 = new runnableTest3("张三","土匪");
   runnableTest3 r2 = new runnableTest3("李四","警察");
   runnableTest3 r3 = new runnableTest3("王五","警察");
   runnableTest3 r4 = new runnableTest3("竹柳","警察");
   runnableTest3 r5 = new runnableTest3("小明","土匪");
   Thread th1 = new Thread(r1);//这里调用的是线程Thread的带一个参数的构造方法
   Thread th2 = new Thread(r2);
   Thread th3 = new Thread(r3);
   Thread th4 = new Thread(r4);
   Thread th5 = new Thread(r5);
   th1.start();
   th2.start();
   th3.start();
   th4.start();
   th5.start();
   
 }
}

 

 

4.

package lianxi.threadTest;
/**
 * 以继承Thread类的方式实现线程
 *
 */
public class ThreadTest extends Thread{
 
 private String name;//姓名
 private String role;//角色
 public ThreadTest(String name, String role) {
  super();//构造函数默认情况下调用了父类的无参构造函数
  this.name = name;
  this.role = role;
 }
   public void move(){
    for(int i=0;i<10;i++){
     System.out.println(this.name+"移动了"+i+"米");
    }
   }
    @Override
 public void run() {
  //super.run();
  move();
  try {
   sleep(100000);
  } catch (InterruptedException e) {
   // TODO Auto-generated catch block
   e.printStackTrace();
  }
 }
   public static void main(String[] args) {
    ThreadTest  t1 = new ThreadTest("小强","土匪");
    ThreadTest  t2 = new ThreadTest("小时","土匪");
    ThreadTest  t3 = new ThreadTest("小米","警察");
    //启动线程
    t1.start();//构造函数默认情况下调用了父类(线程)的无参构造函数
    t2.start();
    t3.start();
 }

}

 

5.卖票过程

package lianxi.tickets;


/**
 * 1.Tickets extends Thread
 * 2.Tickets implements Runnable
 * 在使用线程做题的时候首先要考虑用上面的两种方式的哪一种。
 * 由于java中类的单继承多实现的,因此一般采用实现接口的方法。因为类如果继承了Thread以后就不能继承其他类了。
 *
 */
public class Tickets implements Runnable{

 int ticket=100;//票数
 
 /**1.重写接口中抽象的方法
  * 2.为了线程安全都会用到synchronized同步。
  * 3.当同步方法的时候,结果只能是一个窗口售票100张,因此只能用同步代码块的方法,把synchronized写在方法里
  * 4.当synchronized写在while外面的时候,其实效果跟同步方法一样了,因为synchronized控制了整个方法体,那么synchronized只能写在while循环里
  * 5.synchronized写在循环里,可是当一个进程正在执行synchronized里面的第一句话的时候,其他线程可能会去执行while(ticket>0),因为
  * while(ticket>0)这行代码并没被加锁(synchronized)。。这样导致的结果就是在最后一张票的时候会四个窗口都卖。(因为一个窗口在卖票的时候其他在三个窗口
  * 已经执行完了while(ticket>0)这行代码,这就导致了多买了三张票(0,-1,-2)
  * 6.解决这个问题,给需要执行的语句加上限制条件,if(ticket>0)
  */
 public void run() {
  while(ticket>0){
   synchronized ("ssss") { 
    if(ticket>0){
           System.out.println(Thread.currentThread().getName()+"卖出第"+ticket+"票");//synchronized里面的第一句话的时候
           ticket--;        
   }
   }
  } 
 }
 public static void main(String[] args) {
      Tickets t = new Tickets();//创建一个对象
  Thread t1 =new Thread(t,"seller1");//用这个对象封装四个线程(调用Thread两个参数的构造函数),代表四个窗口
  Thread t2 =new Thread(t,"seller2");
  Thread t3 =new Thread(t,"seller3");
  Thread t4 =new Thread(t,"seller4");
  t1.start();//开启线程,默认调用run()方法
  t2.start();
  t3.start();
  t4.start();
 }

}

6.转账过程

package com.bank;


public class Bank {//deposit存款  transfer转账
 static int money=100;
 
 
 public synchronized static void deposit(int am){
   money=money+am;
  System.out.println("存款成功,余额为:"+money);
 }
 public synchronized static void transfer(int bm){
  if(money>=bm){
    money=money-bm;
   System.out.println("转账成功,余额为:"+money);
  }else{
   System.out.println("余额不足");
  }
 }


 

}

 

package com.bank;
/**
 *
 *两个人都能操作一个银行卡
 *
 */
public class Customer extends Thread{
 public  void run(){
  System.out.println(Thread.currentThread().getName());
  Bank.deposit(100);
  System.out.println(Thread.currentThread().getName());
     Bank.transfer(120);
 }
 public static void main(String[] args) {
  Customer c = new Customer();
  Thread t1=new Thread(c,"用户1");
  Thread t2=new Thread(c,"用户2");
  t1.start();
  t2.start();
 }

}

 

分享到:
评论

相关推荐

    单线程与多线程的区别

    单线程与多线程的区别主要体现在资源管理和执行效率上。 **单线程**: 1. **定义**:单线程意味着一个进程只有一个执行线程。这意味着,任何时刻只有一个任务或操作可以被处理。 2. **优点**:由于只有一个线程,...

    单线程与多线程socket通信

    在代码实现上,单线程与多线程的主要区别在于处理客户端连接的方式。在单线程中,所有通信都在同一个线程内完成;而在多线程中,每个客户端连接都会启动一个新的线程。这会影响到程序的并发处理能力和响应速度。为了...

    C#单线程与多线程实例

    本文将深入探讨C#中的单线程与多线程实例,帮助你理解它们的区别,并提供相关的实践示例。 一、单线程 单线程意味着一个应用程序只有一个执行线程。在这种情况下,程序按照预定的顺序执行任务,一次只能处理一个...

    单线程与多线程python爬虫地图瓦片源码

    本文将深入探讨“单线程与多线程Python爬虫地图瓦片源码”的相关知识点。 首先,我们需要理解“线程”这一概念。线程是程序执行的最小单元,每个线程负责执行特定的任务。在单线程环境中,程序按顺序执行,一次只能...

    JAVA单线程多线程

    ### JAVA中的单线程与多线程概念解析 #### 单线程的理解 在Java编程环境中,单线程指的是程序执行过程中只有一个线程在运行。这意味着任何时刻只能执行一个任务,上一个任务完成后才会进行下一个任务。单线程模型...

    e语言-json解析的单线程与多线程操作实例

    资源介绍:json解析的单线程与多线程操作实例,源码非常的简单,多线程是调用了鱼刺的多线程模块。资源作者:

    易语言-json解析的单线程与多线程操作实例

    总的来说,通过分析这个"易语言-json解析的单线程与多线程操作实例",我们可以学习到如何在易语言环境下进行JSON解析,并了解如何利用多线程提升程序执行效率。此外,还可以深入研究线程同步技术,进一步优化多线程...

    多线程计算pi

    单线程与多线程对比 计算量相同,线程数不同 例如,N取1000,000,测试使用1、2、3、4……个线程时所需要的时间。 线程数相同,计算量不同 例如,只考察单线程和双线程的性能对比,N分别取不同的数值。

    多核和单核中多线程及单线程的特点

    在计算机科学领域,多核...理解单线程与多线程的特点,以及如何有效地管理线程同步,是提升软件性能和可靠性的关键。在实际开发中,应根据具体需求选择合适的线程模型,并利用适当的同步机制确保程序的正确性和高效性。

    JavaScript的单线程与多线程:深入理解与应用实践

    本文将深入探讨JavaScript的单线程和多线程概念,解释它们如何影响程序的执行,以及如何在实际开发中利用这些特性。 JavaScript的单线程和多线程模型各有优势和挑战。开发者需要根据应用的具体需求,合理选择并发...

    基于SpringBoot和POI实现单线程和多线程导出Excel.zip

    基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip基于SpringBoot和POI实现单线程和多线程导出Excel.zip...

    多线程与单线程的对比(采用CreateThread)

    多线程实例,采用CreateThread函数。 (1) 该程序还将和单线程做对比。 (2) 由于给线程的函数传递了多个参数,所以采用结构体的方式传递参数。 (3) 为了演示效果,采用了比较耗时的打点处理。

    实例分析Java单线程与多线程

    实例分析Java单线程与多线程 在 Java 中,线程是程序执行的基本单元,每个任务称为一个线程,线程不能独立存在,它必须是进程的一部分。根据线程的数量,Java 程序可以分为单线程和多线程两种。 单线程是最常见的 ...

    C#抓虫单线程和多线程两个

    通过查看和学习这两个项目,可以更深入理解C#中抓虫的单线程与多线程实现方式。 总结,C#抓虫可以通过单线程或多线程实现,单线程简单易懂,适合小规模抓取;多线程则能提升效率,适用于大规模抓取任务。在实际开发...

    java单线程多线程clientserver

    总的来说,理解和掌握Java的单线程与多线程是成为一名优秀的Java开发者必备的技能。在客户端-服务器场景下,合理运用多线程可以显著提升系统的并发处理能力和性能。而处理好线程安全和并发控制,是保证系统稳定性和...

    单、多线程断点续传下载

    在IT领域,尤其是在移动应用开发中,特别是在Android平台,单线程与多线程断点续传下载是一项关键的技术。断点续传允许用户在下载过程中暂停并继续,而不会丢失已下载的数据,这对于处理大文件或网络不稳定的情况...

    vc++分别用单-多线程读取数字

    单线程与多线程的性能差异取决于具体的应用场景。在读取数字这种简单任务中,多线程可能不会带来显著的性能提升,因为I/O操作(如键盘输入)往往是阻塞的,无法被并行化。但在处理大量计算密集型任务时,多线程可以...

Global site tag (gtag.js) - Google Analytics