java 网络编程connection timed out是什么意思_什么?听说这四个概念,很多 Java 老手都说不清...

Java 是很多人一直在用的编程语言,但是有些 Java 概念是非常难以理解的,哪怕是一些多年的老手,对某些 Java 概念也存在一些混淆和困惑。

所以,在这篇文章里,会介绍四个 Java 中最难理解的四个概念,去帮助开发者更清晰的理解这些概念:

  1. 匿名内部类的用法
  2. 多线程
  3. 如何实现同步
  4. 序列化

匿名内部类

匿名内部类又叫匿名类,它有点像局部类(Local Class)或者内部类(Inner Class),只是匿名内部类没有名字,我们可以同时声明并实例化一个匿名内部类。

一个匿名内部类仅适用在想使用一个局部类并且只会使用这个局部类一次的场景。

匿名内部类是没有需要明确声明的构造函数的,但是会有一个隐藏的自动声明的构造函数。

创建匿名内部类有两种办法:

  1. 通过继承一个类(具体或者抽象都可以)去创建出匿名内部类
  2. 通过实现一个接口创建出匿名内部类

咱们看看下面的例子:

interface Programmer {    void develop();}
public class TestAnonymousClass {    public static Programmer programmer = new Programmer() {        @Override        public void develop() {            System.out.println("我是在类中实现了接口的匿名内部类");        }    };public static void main(String[] args) {        Programmer anotherProgrammer = new Programmer() {            @Override            public void develop() {                System.out.println("我是在方法中实现了接口的匿名内部类");            }        };TestAnonymousClass.programmer.develop();        anotherProgrammer.develop();    }}

从上面的例子可以看出,匿名类既可以在类中也可以在方法中被创建。

之前我们也提及匿名类既可以继承一个具体类或者抽象类,也可以实现一个接口。所以在上面的代码里,我创建了一个叫做 Programmer 的接口,并在 TestAnonymousClass 这个类中和 main() 方法中分别实现了接口。

Programmer除了接口以外既可以是一个抽象类也可以是一个具体类。

抽象类,像下面的代码一样:

public abstract class Programmer {    public abstract void develop();}

具体类代码如下:

public class Programmer {    public void develop() {        System.out.println("我是一个具体类");    }}

OK,继续深入,那么如果 Programmer 这个类没有无参构造函数怎么办?我们可以在匿名类中访问类变量吗?我们如果继承一个类,需要在匿名类中实现所有方法吗?

public class Programmer {    protected int age;public Programmer(int age) {        this.age = age;    }public void showAge() {        System.out.println("年龄:" + age);    }public void develop() {        System.out.println("开发中……除了异性,他人勿扰");    }public static void main(String[] args) {        Programmer programmer = new Programmer(38) {            @Override            public void showAge() {                System.out.println("在匿名类中的showAge方法:" + age);            }        };        programmer.showAge();    }}
  1. 构造匿名类时,我们可以使用任何构造函数。上面的代码可以看到我们使用了带参数的构造函数。
  2. 匿名类可以继承具体类或者抽象类,也能实现接口。所以访问修饰符规则同普通类是一样的。子类可以访问父类中的 protected 限制的属性,但是无法访问 private 限制的属性。
  3. 如果匿名类继承了具体类,比如上面代码中的 Programmer 类,那么就不必重写所有方法。但是如果匿名类继承了一个抽象类或者实现了一个接口,那么这个匿名类就必须实现所有没有实现的抽象方法。
  4. 在一个匿名内部类中你不能使用静态初始化,也没办法添加静态变量。
  5. 匿名内部类中可以有被 final 修饰的静态常量。

匿名类的典型使用场景

  1. 临时使用:我们有时候需要添加一些类的临时实现去修复一些问题或者添加一些功能。为了避免在项目里添加java文件,尤其是仅使用一次这个类的时候,我们就会使用匿名类。
  2. UI Event Listeners:在java的图形界面编程中,匿名类最常使用的场景就是去创建一个事件监听器。比如:
button.setOnClickListener(new View.OnClickListener() {    public void onClick(View v) {    }});

上面的代码中,我们通过匿名类实现了 setOnClickListener 接口,当用户点击按钮的时候,就会触发我们实现的 onClick 方法。

多线程

Java 中的多线程就是利用多个线程共同完成一个大任务的运行过程,使用多线程可以最大程度的利用CPU。

使用多线程的使用线程而不是进程来做任务处理,是因为线程比进程更加轻量,线程是一个轻量级的进程,是程序执行的最小单元,并且线程和线程之间是共享主内存的,而进程不是。

线程生命周期

4dddb1f569240161dea88c883c9a2271.png

正如上图所示,线程生命周期一共有六种状态。我们现在依次对这些状态进行介绍。

  1. New:当我们构造出一个线程实例的时候, 这个线程就拥有了 New 状态。这个状态是线程的第一个状态。此时,线程并没有准备运行。
  2. Runnable:当调用了线程类的 start() 方法, 那么这个线程就会从 New 状态转换到 Runnable 状态。这就意味着这个线程要准备运行了。但是,如果线程真的要运行起来,就需要线程调度器来调度执行这个线程。但是线程调度器可能忙于在执行其他的线程,从而不能及时去调度执行这个线程。线程调度器是基于 FIFO 策略去从线程池中挑出一个线程来执行的。
  3. Blocked:线程可能会因为不同的情况自动的转为 Blocked 状态。比如,等候 I/O 操作,等候网络连接等等。除此之外,任意的优先级比当前正在运行的线程高的线程都可能会使得正在运行的线程转为 Blocked 状态。
  4. Waiting:在同步块中调用被同步对象的 wait 方法,当前线程就会进入 Waiting 状态。如果在另一个线程中的同一个对象被同步的同步块中调用 notify()/notifyAll(),就可能使得在 Waiting 的线程转入 Runnable 状态。
  5. Timed_Waiting:同 Waiting 状态,只是会有个时间限制,当超时了,线程会自动进入 Runnable 状态。
  6. Terminated:线程在线程的 run() 方法执行完毕后或者异常退出run()方法后,就会进入 Terminated 状态。

为什么要使用多线程

大白话讲就是通过多线程同时做多件事情让 Java 应用程序跑的更快,使用线程来实行并行和并发。如今的 CPU 都是多核并且频率很高,如果单独一个线程,并没有充分利用多核 CPU 的优势。

重要的优势

  • 可以更好地利用 CPU
  • 可以更好地提升和响应性相关的用户体验
  • 可以减少响应时间
  • 可以同时服务多个客户端

创建线程有两种方式

  1. 通过继承Thread类创建线程

这个继承类会重写 Thread 类的 run() 方法。一个线程的真正运行是从 run() 方法内部开始的,通过 start() 方法会去调用这个线程的 run() 方法。

public class MultithreadDemo extends Thread {    @Override    public void run() {        try {            System.out.println("线程 " +  Thread.currentThread().getName() + " 现在正在运行");        } catch (Exception e) {            e.printStackTrace();        }    }public static void main(String[] args) {        for (int i = 0; i < 10; i++) {            MultithreadDemo multithreadDemo = new MultithreadDemo();            multithreadDemo.start();        }    }}
  1. 通过实现Runnable接口创建线程

我们创建一个实现了 java.lang.Runnable 接口的新类,并实现其 run() 方法。然后我们会实例化一个 Thread 对象,并调用这个对象的 start() 方法。

public class MultithreadDemo implements Runnable {@Override    public void run() {        try {            System.out.println("线程 " + Thread.currentThread().getName() + " 现在正在运行");        } catch (Exception e) {            e.printStackTrace();        }    }public static void main(String[] args) {        for (int i = 0; i < 10; i++) {            Thread thread = new Thread(new MultithreadDemo());            thread.start();        }    }}

两种创建方式对比

  • 如果一个类继承了 Thread 类,那么这个类就没办法继承别的任何类了。因为 Java 是单继承,不允许同时继承多个类。多继承只能采用接口的方式,一个类可以实现多个接口。所以,使用实现 Runnable 接口在实践中比继承 Thread 类更好一些。
  • 第一种创建方式,可以重写 yield()、interrupt() 等一些可能不太常用的方法。但是如果我们使用第二种方式去创建线程,则 yield() 等方法就无法重写了。

同步

同步只有在多线程条件下才有意义,一次只能有一个线程执行同步块。

在 Java 中,同步这个概念非常重要,因为 Java 本身就是一门多线程语言,在多线程环境中,做合适的同步是极度重要的。

为什么要使用同步

在多线程环境中执行代码,如果一个对象可以被多个线程访问,为了避免对象状态或者程序执行出现错误,对这个对象使用同步是非常必要的。

在深入讲解同步概念之前,我们先来看看同步相关的问题。

class Production {//没有做方法同步    void printProduction(int n) {        for (int i = 1; i <= 5; i++) {            System.out.print(n * i+" ");            try {                Thread.sleep(400);            } catch (Exception e) {                System.out.println(e);            }        }}}
class MyThread1 extends Thread {Production p;MyThread1(Production p) {        this.p = p;    }public void run() {        p.printProduction(5);    }
}
class MyThread2 extends Thread {Production p;MyThread2(Production p) {        this.p = p;    }public void run() {        p.printProduction(100);    }}
public class SynchronizationTest {    public static void main(String args[]) {        Production obj = new Production(); //多线程共享同一个对象        MyThread1 t1 = new MyThread1(obj);        MyThread2 t2 = new MyThread2(obj);        t1.start();        t2.start();    }}

运行上面的代码后,由于我们没有加同步,可以看到运行结果非常混乱。

Output:100 5 10 200 15 300 20 400 25 500

接下来,我们给 printProduction 方法加上同步:

class Production {//做了方法同步    synchronized void printProduction(int n) {        for (int i = 1; i <= 5; i++) {            System.out.print(n * i+" ");            try {                Thread.sleep(400);            } catch (Exception e) {                System.out.println(e);            }        }}}

当我们对 printProduction() 加上了同步(synchronized)后, 已有一个线程执行的情况下,是不会有任何一个线程可以再次执行这个方法。这次加了同步后的输出结果是有次序的。

Output:5 10 15 20 25 100 200 300 400 500

类似于对方法做同步,你也可以去同步 Java 类和对象。

注意:其实有时候我们可以不必去同步整个方法。出于性能原因,我们其实可以仅同步方法中我们需要同步的部分代码。被同步的这部分代码就是方法中的同步块。

序列化

Java 的序列化就是将一个 Java 对象转化为一个字节流的一种机制。从字节流再转回 Java 对象叫做反序列化,是序列化的反向操作。

序列化和反序列化是和平台无关的,也就是说你可以在 Linux 系统序列化,然后在 Windows 操作系统做反序列化。

如果要序列化对象,需要使用 ObjectOutputStream 类的 writeObject() 方法。如果要做反序列化,则要使用 ObjectOutputStream 类的 readObject() 方法。

如下图所示,对象被转化为字节流后,被储存在了不同的介质中。这个流程就是序列化。在图的右边,也可以看到从不同的介质中,比如内存,获得字节流并转化为对象,这叫做反序列化。

833809f78be4d429b688e598f8eb2b31.png

为什么使用序列化

如果我们创建了一个 Java 对象,这个对象的状态在程序执行完毕或者退出后就消失了,不会得到保存。

所以,为了能解决这类问题,Java 提供了序列化机制。这样,我们就能把对象的状态做临时储存或者进行持久化,以供后续当我们需要这个对象时,可以通过反序列化把对象还原回来。

下面给出一些代码看看我们是怎么来做序列化的。

import java.io.Serializable;
public class Player implements Serializable {private static final long serialVersionUID = 1L;private String serializeValueName;    private transient String nonSerializeValuePos;public String getSerializeValueName() {        return serializeValueName;    }public void setSerializeValueName(String serializeValueName) {        this.serializeValueName = serializeValueName;    }public String getNonSerializeValueSalary() {        return nonSerializeValuePos;    }public void setNonSerializeValuePos(String nonSerializeValuePos) {        this.nonSerializeValuePos = nonSerializeValuePos;    }@Override    public String toString() {        return "Player [serializeValueName=" + serializeValueName + "]";    }}
import java.io.FileOutputStream;import java.io.IOException;import java.io.ObjectOutputStream;
public class SerializingObject {    public static void main(String[] args) {Player playerOutput = null;        FileOutputStream fos = null;        ObjectOutputStream oos = null;playerOutput = new Player();        playerOutput.setSerializeValueName("niubi");        playerOutput.setNonSerializeValuePos("x:1000,y:1000");try {            fos = new FileOutputStream("Player.ser");            oos = new ObjectOutputStream(fos);            oos.writeObject(playerOutput);System.out.println("序列化数据被存放至Player.ser文件");oos.close();            fos.close();        } catch (IOException e) {e.printStackTrace();        }    }}

Output:序列化数据被存放至Player.ser文件

import java.io.FileInputStream;import java.io.IOException;import java.io.ObjectInputStream;
public class DeSerializingObject {public static void main(String[] args) {Player playerInput = null;        FileInputStream fis = null;        ObjectInputStream ois = null;try {            fis = new FileInputStream("Player.ser");            ois = new ObjectInputStream(fis);            playerInput = (Player) ois.readObject();System.out.println("从Player.ser文件中恢复");ois.close();            fis.close();        } catch (IOException | ClassNotFoundException e) {            e.printStackTrace();        }System.out.println("player名字为 : " + playerInput.getSerializeValueName());        System.out.println("player位置为 : " + playerInput.getNonSerializeValuePos());    }}

Output:

从Player.ser文件中恢复player名字为 : niubiplayer位置为 : null

关键特性

  1. 如果父类实现了 Serializable 接口那么子类就不必再实现 Serializable 接口了。但是反过来不行。
  2. 序列化只支持非 static 的成员变量
  3. static 修饰的变量和常量以及被 transient 修饰的变量是不会被序列化的。所以,如果我们不想要序列化某些非 static 的成员变量,直接用 transient 修饰它们就好了。
  4. 当反序列化对象的时候,是不会调用对象的构造函数的。
  5. 如果一个对象被一个要序列化的对象引用了,这个对象也会被序列化,并且这个对象也必须要实现 Serializable 接口。

总结

首先,我们介绍了匿名类的定义,使用场景和使用方式。

其次,我们讨论了多线程和其生命周期以及多线程的使用场景。

再次,我们了解了同步,知道同步后,仅同时允许一个线程执行被同步的方法或者代码块。当一个线程在执行被同步的代码时,别的线程只能在队列中等待直到执行同步代码的线程释放资源。

最后,我们知道了序列化就是把对象状态储存起来以供后续使用。

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/506819.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

assembly 输出ab中所有数_.NET Core中批量注入Grpc服务

(给DotNet加星标&#xff0c;提升.Net技能)转自&#xff1a;张子浩cnblogs.com/ZaraNet/p/12167517.htmlGRPC 是谷歌发布的一个开源、高性能、通用RPC服务&#xff0c;尽管大部分 RPC 框架都使用 TCP 协议&#xff0c;但其实 UDP 也可以&#xff0c;而 gRPC 干脆就用了 HTTP2。…

kdj指标主要看哪个值_悟空CRM:在线crm主要看这两个指标,都非常重要!

crm对很多企业都非常重要&#xff0c;可是很多人并不明白crm到底重要在哪些地方&#xff1f;比如说很多人都比较喜欢使用这个系统&#xff0c;尤其是在线crm。 在线crm主要看这两个指标&#xff0c;都非常重要&#xff0c;这两个指标如果上去了&#xff0c;基本上对企业的运营都…

鼠标控制视角wasd移动_绝地求生:为什么控制方向键是WASD?网友:就不能是其他键位吗?...

哈喽&#xff0c;大家好这里是大能有话说&#xff0c;现在的网络游戏越来越发达&#xff0c;每个游戏的玩法有非常多种&#xff0c;但是不知道小伙伴们有没有发现&#xff0c;在需要控制方向的情况下&#xff0c;咱们用的都是W、A、S、D这四个键&#xff0c;那为什么偏偏就一定…

javawed商店商品结算_微信小商店搭建

点击上方蓝字关注我吧个人也能搭建微信小商店了&#xff0c;直接下单&#xff0c;微信立马到账&#xff0c;方便快捷&#xff0c;对于个人来说&#xff0c;在网上卖东西&#xff0c;有了一个利于客户下单的渠道。1、微信小商店介绍为了进一步降低进入小程序生态经营和卖货的门槛…

图片还原去遮挡_斗罗:这届coser太强,动画刚播出两天,战损三哥就被还原了...

斗罗大陆作为玄机旗下的热门动画&#xff0c;不仅多次登上热搜&#xff0c;引发漫迷热议&#xff0c;还吸引了众位coser的注意力。作品从开播到现在&#xff0c;基本上绝大多数角色都曾被coser还原过。对于里面的热门角色&#xff0c;例如史莱克七怪&#xff0c;几乎是每更换一…

熟悉html css,编写HTML和CSS的前端开发中不一定熟悉JavaScript

原标题&#xff1a;编写HTML和CSS的前端开发中不一定熟悉JavaScript作为前端开发人员&#xff0c;HTML、css、Java是必备的知识技能&#xff0c;但是现实工作工作中并非所有的前端都知道Java&#xff0c;根据外国一个网站的匿名调查发现&#xff0c;有17%的开发人员不知道Java&…

fastapi 传输文件存文件_揭秘|国内影视文件传输的真相,跨境文件传输更不简单...

2020年影视行业至黑时刻总算要过去了&#xff0c;下半年复苏迹象已经显现。作为影视行业的基础搬运工&#xff0c;文件传输贯穿始末。无论是TB级原始素材还是后期协作的大文件&#xff0c;多团队高效协作必然要考虑大文件传输这个基础工具。在选择文件传输软件这件事上&#xf…

计算机考csp200分啥水平,计算机与信息工程学院成功举办第20次CCF CSP认证考试

2020年9月13日&#xff0c;计算机与信息工程学院在计算机大楼201举办第二十次CCF CSP认证考试。这是计算机与信息工程学院2019年12月与中国计算机学会签署协议、河南大学正式成为CSP认证考点以来&#xff0c;举办的首次CCF CSP认证考试。本次认证考试历时四个小时&#xff0c;共…

gta5显示nat较为严格_为何严格治理下雾霾天仍频发?哈尔滨市环保局解答重污染天3大疑问...

哈尔滨市环保局副局长姚玮晶解答近期重污染天三疑问我省与吉林大气污染或将联防联控气象条件不利秸秆焚烧集中 是雾霾主因今年供暖季以来&#xff0c;冰城污染天频发&#xff0c;与去年同期相比&#xff0c;重污染天气有所增多。自2013年冰城爆发大规模雾霾以来&#xff0c;省市…

中国科技大学计算机考研复试内容,中国科学技术大学考研复试

出国留学网考研网为大家提供中国科学技术大学材料科学与工程学院2018考研复试内容&#xff0c;更多考研资讯请关注我们网站的更新!中国科学技术大学材料科学与工程学院2018考研复试内容为进一步规范硕士生复试工作&#xff0c;确保复试工作的有效性和公平、公开、公正原则&…

单片机搭建环境烧录方法_单片机仿真器的工作原理解析

仿真器出现的原因1、早期的单片机内部没有ROM&#xff0c;比如8031、8032&#xff0c;这种单片机只能外部扩展紫外擦除的EPROM存储器&#xff0c;就是芯片上带窗口的ROM。紫外擦除的ROM需要用紫外灯照射较长时间(10分钟或者更多)才能擦掉芯片中的内容以便写入新的程序。2、有的…

分布式存储图解_BERT的youxiu变体:ALBERT论文图解介绍

作者&#xff1a;amitness编译&#xff1a;ronghuaiyang正文共&#xff1a; 3116 字 21 图预计阅读时间&#xff1a; 9 分钟原文链接&#xff1a;BERT的youxiu变体&#xff1a;ALBERT论文图解介绍​mp.weixin.qq.comALBERT作为BERT的一个变体&#xff0c;在保持性能的基础上&am…

数据分析转软件测试,(转)性能测试用户模型(三):基础数据分析、场景数据...

作者&#xff1a;薛定谔的破猫基础数据分析以下图表均取自互联网&#xff0c;本文是在“已经获取所需数据”的前提下&#xff0c;讲解性能测试的一些设计思路。至于如何才能取得这些数据&#xff0c;将在后续的文章中说明。系统访问量分布由系统的日访问量分布图&#xff0c;可…

王者体验服服务器注册人数已满,王者官方大厅奖励有多难获得?服务器直接崩溃,玩家:别发红包了...

可乐要加冰&#xff0c;乔妹在你心&#xff0c;大家好我是小乔妹&#xff0c;每天为您分享有趣的王者资讯&#xff0c;感谢您的关注。王者荣耀一直以来都有许许多多的活动&#xff0c;有限时活动也有长久活动&#xff0c;但官方专属大厅奖励活动确实王者史上第一次奖励&#xf…

cmd输入pip报错_使用Pip管理Python的包

这是我的Python教程的第2篇文章第1篇文章在这里:Python安装0x01Pip介绍Pip是Python的包管理程序,负责Python的包的查找,下载,安装,卸载工作;使用Pip可以轻松的管理Python成千上万的第三包,使你在Python程序的开发如鱼得水0x02使用Pip确保已经把Python的路径添加进系统路径右键我…

jenkins部署流程图_一文教你使用 Jenkins 设计多环境、多项目持续集成环境!

自动化部署主要是为了解决项目多、环境多、持续集成慢、部署操作麻烦、手动操作易出错、自动化运维等问题。Jenkins是开源CI&CD软件领导者&#xff0c; 提供超过1000个插件来支持构建、部署、自动化&#xff0c; 满足任何项目的需要。目标&#xff1a;支持多分支、多环境、…

udp 使用connect优点_一文搞懂TCP和UDP的区别

TCP(Transmission Control Protocol&#xff0c;传输控制协议)和UDP(User Data Protocol ,用户数据报协议)都属于TCP/IP协议簇。TCP/IP协议集包括了超文本传输协议(HTTP)、文本传输协议(FTP)、远程登录协议(Telnet)、internet协议(IP)、internet控制信息协议(IMCP)等&#xff0…

小森生活显示无可用服务器,《小森生活》无可用游戏服务器解决教程 无可用网关服务器怎么办...

导读小森生活无可用网关服务器是什么意思&#xff1f;怎么解决&#xff1f;小森生活无可用网关服务器这个提示在进入游戏中会出现哦&#xff0c;很多玩家都无法正常进入游戏怎么解决呢&#xff0c;现在就来告诉给大家详细解决方法吧~小森生活无可用游戏服务器...小森生活无可用…

矢量归一化_浅析矢量网络分析仪误差模型及校准

最近跟业界一位同仁讨论了矢量网络分析仪的误差模型及校准过程&#xff0c;简单整理了一下&#xff0c;分享给大家&#xff0c;欢迎一起讨论。矢网的误差模型确实不太好理解&#xff0c;一般只有研发矢网或者专攻测试技术的人员才会深入探究。使用矢网测试之前&#xff0c;都是…

数据库表名大小写_某教程学习笔记(一):09、MYSQL数据库漏洞

她其实并不喜欢你&#xff0c;只是在寂寞的时候&#xff0c;你刚好撞上去&#xff0c;刚好你对她好&#xff0c;刚好你能入她眼&#xff0c;刚好她来着不拒&#xff0c;这所有都是刚好。。。---- 网易云热评一、MYSQL语句创建数据库create database test;选择要操作的数据库use…