• [分享交流] 如何解决“dos命令窗口可以执行java命令,无法执行javac命令”
    背景作为小白参与了“Java编程创造营”活动,老师在“Java编程基础课程”讲到java程序安装和环境配置。问题复现根据老师的流程成功安装了java8,配置完环境变量,在dos下成功检测到java版本:创建 HelloWorld.java/** * @author amufeng * @version v1.0 */ public class HelloWorld{ public static void main(String[] args){ int x=-1; x=x>>>5; System.out.print("Hi Java"+x); System.out.println("Hi Javavavava"); System.out.println("Javavavava"); } }执行编译HelloWorld.java,提示“‘javac’不是内部或外部命令,也不是可运行的程序或批处理文件”问题分析查看了一些CSDN博客,明确问题是环境变量配置不正确导致的。又查了一些资料,确认“java”命令属于JDK,而“javac”命令属于JRE,另一方面JRE属于JDK的一部分。问题可能是JRE的环境变量配置异常(或者缺少配置)。解决方法配置JDK和JRE环境变量:Path中添加JDK/JRE目录:重启电脑,再试javac命令,运行成功。编译、执行java程序:结束至此“dos命令窗口可以执行java命令,无法执行javac命令”问题解决,希望对有缘人有帮助。
  • [全栈开发者] (活动已结束)【Java编程创造营】第一阶段·最终考核
    经过一个月的学习,相信大家对Java有了基本的了解和认知我们迎来了第一阶段的最终考核请大家认真阅读考核要求,避免无法考核认证*报名活动才能参加最终考核  点此报名考核截止时间6月30日(超出考核时间不计入成绩)请遵守考试秩序,考试之前请务必仔细阅读以下注意事项:1)正式考试前请确定邮箱已绑定,如未绑定的,请登录华为云官网,按照出现的页面完成邮箱绑定。2)考试请使用Google Chrome(48版本以上)浏览器完成。3)考试次数为5次,请珍惜考试机会。每次考试会从题库中随机抽题。4)考试时间为40分钟,考试期间无法暂停,一旦超时,系统将自动提交试卷。交卷后即可查看到成绩。5)考试共25题,题型包括判断、单选和多选,总分100分,80分及以上即可通过考试,可直接获得阶段一结业电子证书6)考试过程中若有截屏或切屏行为,系统将发出警告,切屏次数达到5次,系统将自动提交试卷7)点击开始考试后,请耐心等待系统抽题,切勿重复刷新页面,否则导致题目抽取错误,成绩将会被作废。集齐三阶段电子证书可获得【Java编程创造营】结业实体证书考核流程Step1:进行Java开发技能考核点击进行Java开发技能测评(初级)Step2:考核后请将信息填写到有奖问卷中点击填写考核信息收集问卷阶段学习排行榜不仅有学习纪念证书,我们还为参与学习打卡的同学准备了实物奖品奖励通过获取积分,积分排行的方式获得奖励1)学习打卡赢积分学习第一阶段课程:Java编程基础课程:点此学习序号阶段任务详情活动积分奖励附加奖励提交入口1每章随堂测试任务完成方式:在随堂测试打卡帖中,回复对应章节的随堂    回复格式:华为云ID+截图(露出右上角华为云ID,且有效回复次数≥1)2分 /每有效打卡/每章节每周在本周内提交随堂测试的用户中,抽取1名幸运奖励华为云定制鼠标*1点击前往2每周学习笔记分享任务完成方式:在学习笔记征集帖中,回复本周课程内容的学习笔记    回复格式:华为云ID+笔记内容(字数≥200字)2分 /每有效打卡/每周每周在本周内提交学习笔记的用户中,抽取1名幸运奖励华为云定制鼠标*1点击前往3相关文章征集任务完成方式:本学习阶段任意时间内,在“华为云-博客”,发表与学习内容相关的任意原创博客内容,将文章链接回复到指定帖内    回复格式:华为云ID+博客文章链接(字数≥600字)5积分 /每篇有效心得/每阶段 最高10/每阶段每阶段选取1篇最佳博文,奖励机械键盘*1点击前往4问答官排位赛任务完成方式:用户可在相关活动帖中发布自己学习中的疑惑或实践问题,其他用户可参与回答。由专家评审,同一问题下确定一名最佳答案。回复格式:华为云ID+提问的问题/解答答案5积分/每有效问题(最高10分)2积分/每有答复(最高4分)最终会全部每阶段参与互动的用户中,抽取3位幸运奖奖励华为云定制鼠标*1点击前往5完成阶段沙箱实验完成规定的沙箱实验20分/ 沙箱实验/点击前往6完成相关微认证完成规定的微认证并获得微认证证书(官方认证)30分/认证/点击前往点击了解Java编程创造营专属产品福利2)参加限时活动赢积分【有奖征文】奔跑吧,JAVA!-- 26周年特别策划今年五月,编程语言—JAVA迎来了自己的第26个生日。华为云社区特举办 Java主题征文活动,来庆祝这个属于技术的节日参与征文活动将会有机会获得精美礼品,优秀的文章还将被汇编成册,提供实践参考。报名【Java编程创造营】并参与此有奖征文活动将会获得额外积分加分发表文章+5分/篇(上限20分),TOP20文章 +10分/篇(上限20分)参与本次征文活动后,将参与活动的文章链接私信给小助手视为参与成功,活动时间与征文时间同步。征文活动参与详情请见:https://bbs.huaweicloud.com/blogs/265241-----------------------------------------------------------------------------------------注意事项:○获奖名单将在活动结束后3个工作日内公示。如如有异议请于【华为云课程小助手】联系○所有活动奖品将在活动公示后15个工作日内完成发放;○活动奖品颜色、型号随机,且部分奖品数量有限发完即止,,若有缺货或其他情况将替换为同价值的其他奖品;○本次活动回帖内容需满足华为云论坛发帖规范:https://bbs.huaweicloud.com/forum/thread-23077-1-1.html想了解更多关于课程内容请移步主帖:https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=125761
  • [二次开发] HD 6.5.1.7 Elasticsearch  用java代码查询出来的结果是科学计数法,有没有什么方法让直接返回数值型,不
    【操作步骤&问题现象】head插件查询出来的结果不以科学记数法表示,java代码查询的聚合结果是科学记数法索引中原字段是double目前只想到一个一个通过DecimalFormat解析结果做格式化处理,但这样太麻烦。ES中是否有直接指定格式返回的方式?还有比较奇怪的是数值只有 266144704 也不算大,但还以科学记数法显示了。
  • [全栈开发者] 【Java编程创造营】Java相关沙箱实验打卡贴
    为了巩固大家的学习成果,紧跟学习进度请将需要完成的相关沙箱实验按要求回复到本帖下方按要求格式回复即可获得积分累计阶段奖品,还能有机会获得附加幸运奖哦~征集时间课程全阶段微认证考核要求提交操作结果截图 阶段考核+20分通过特定场景化学习和实际操作,可以实现对学习内容的理解和认知Java编程创造营使用以下场景参与认证考核通过鲲鹏开发套件实现Java代码迁移沙箱链接:https://lab.huaweicloud.com/testdetail_439?ticket=ST-929855-D7amfkTdlHCyKpohgDOjudkO-sso参与认证的同学请将【已完成100%&实验报告截图+华为云ID】回复到本帖当中 才能算作最终考核成功,考核分数才能统计活动注意事项1. 学习任务提交后,小助手会在本阶段学习周期内,按序完成审核,并增加活动积分;2. 本次活动通过完成微认证任务,可获得的积分上限为20分;3. 请务必按照上述要求提交内容,以免影响积分增加;4. 若积分值相同则以完成学习任务的时间先后排序,其中任务完成时间的判定优先级为:相关微认证>阶段沙箱实验>每周学习笔记>问答官排位赛>每章随堂测验打卡5. 其他积分获取方式请查看活动社群公告。想了解更多关于课程内容请移步主帖:https://bbs.huaweicloud.com/forum/forum.php?mod=viewthread&tid=125761
  • [技术干货] Java 多线程编程
    新建状态:使用 new 关键字和 Thread 类或其子类建立一个线程对象后,该线程对象就处于新建状态。它保持这个状态直到程序 start() 这个线程。就绪状态:当线程对象调用了start()方法之后,该线程就进入就绪状态。就绪状态的线程处于就绪队列中,要等待JVM里线程调度器的调度。运行状态:如果就绪状态的线程获取 CPU 资源,就可以执行 run(),此时线程便处于运行状态。处于运行状态的线程最为复杂,它可以变为阻塞状态、就绪状态和死亡状态。阻塞状态:如果一个线程执行了sleep(睡眠)、suspend(挂起)等方法,失去所占用资源之后,该线程就从运行状态进入阻塞状态。在睡眠时间已到或获得设备资源后可以重新进入就绪状态。可以分为三种:等待阻塞:运行状态中的线程执行 wait() 方法,使线程进入到等待阻塞状态。同步阻塞:线程在获取 synchronized 同步锁失败(因为同步锁被其他线程占用)。其他阻塞:通过调用线程的 sleep() 或 join() 发出了 I/O 请求时,线程就会进入到阻塞状态。当sleep() 状态超时,join() 等待线程终止或超时,或者 I/O 处理完毕,线程重新转入就绪状态。死亡状态:一个运行状态的线程完成任务或者其他终止条件发生时,该线程就切换到终止状态。线程的优先级每一个 Java 线程都有一个优先级,这样有助于操作系统确定线程的调度顺序。Java 线程的优先级是一个整数,其取值范围是 1 (Thread.MIN_PRIORITY ) - 10 (Thread.MAX_PRIORITY )。默认情况下,每一个线程都会分配一个优先级 NORM_PRIORITY(5)。具有较高优先级的线程对程序更重要,并且应该在低优先级的线程之前分配处理器资源。但是,线程优先级不能保证线程执行的顺序,而且非常依赖于平台。创建一个线程Java 提供了三种创建线程的方法:通过实现 Runnable 接口;通过继承 Thread 类本身;通过 Callable 和 Future 创建线程。通过实现 Runnable 接口来创建线程创建一个线程,最简单的方法是创建一个实现 Runnable 接口的类。为了实现 Runnable,一个类只需要执行一个方法调用 run(),声明如下:public void run()你可以重写该方法,重要的是理解的 run() 可以调用其他方法,使用其他类,并声明变量,就像主线程一样。在创建一个实现 Runnable 接口的类之后,你可以在类中实例化一个线程对象。Thread 定义了几个构造方法,下面的这个是我们经常使用的:Thread(Runnable threadOb,String threadName);这里,threadOb 是一个实现 Runnable 接口的类的实例,并且 threadName 指定新线程的名字。新线程创建之后,你调用它的 start() 方法它才会运行。void start();下面是一个创建线程并开始让它执行的实例:实例class RunnableDemo implements Runnable { private Thread t; private String threadName; RunnableDemo( String name) { threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + ", " + i); // 让线程睡眠一会 Thread.sleep(50); } }catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { RunnableDemo R1 = new RunnableDemo( "Thread-1"); R1.start(); RunnableDemo R2 = new RunnableDemo( "Thread-2"); R2.start(); } }编译以上程序运行结果如下:Creating Thread-1Starting Thread-1Creating Thread-2Starting Thread-2Running Thread-1Thread: Thread-1, 4Running Thread-2Thread: Thread-2, 4Thread: Thread-1, 3Thread: Thread-2, 3Thread: Thread-1, 2Thread: Thread-2, 2Thread: Thread-1, 1Thread: Thread-2, 1Thread Thread-1 exiting.Thread Thread-2 exiting.通过继承Thread来创建线程创建一个线程的第二种方法是创建一个新的类,该类继承 Thread 类,然后创建一个该类的实例。继承类必须重写 run() 方法,该方法是新线程的入口点。它也必须调用 start() 方法才能执行。该方法尽管被列为一种多线程实现方式,但是本质上也是实现了 Runnable 接口的一个实例。实例class ThreadDemo extends Thread { private Thread t; private String threadName; ThreadDemo( String name) { threadName = name; System.out.println("Creating " + threadName ); } public void run() { System.out.println("Running " + threadName ); try { for(int i = 4; i > 0; i--) { System.out.println("Thread: " + threadName + ", " + i); // 让线程睡眠一会 Thread.sleep(50); } }catch (InterruptedException e) { System.out.println("Thread " + threadName + " interrupted."); } System.out.println("Thread " + threadName + " exiting."); } public void start () { System.out.println("Starting " + threadName ); if (t == null) { t = new Thread (this, threadName); t.start (); } } } public class TestThread { public static void main(String args[]) { ThreadDemo T1 = new ThreadDemo( "Thread-1"); T1.start(); ThreadDemo T2 = new ThreadDemo( "Thread-2"); T2.start(); } }编译以上程序运行结果如下:Creating Thread-1Starting Thread-1Creating Thread-2Starting Thread-2Running Thread-1Thread: Thread-1, 4Running Thread-2Thread: Thread-2, 4Thread: Thread-1, 3Thread: Thread-2, 3Thread: Thread-1, 2Thread: Thread-2, 2Thread: Thread-1, 1Thread: Thread-2, 1Thread Thread-1 exiting.Thread Thread-2 exiting.
  • [技术干货] 浅谈java中的对象、类、与方法的重载
    对象:一切皆为对象。对象包括两部分内容:属性(名词形容词),行为(动词)。对象和对象之间是有关系的: 派生,关联,依赖。类:对同一类别的众多对象的一种抽象。类,还是用来生成对象的一种模板,对象是类的一种具体化的表现。面向对象的三大特性:封装,继承,多态。1234class 类名{访问修饰符 成员变量的定义;访问修饰符 成员函数(方法)的定义; }访问修改符:默认不写,private,public。private,私有。只能被当前class 类名{}中的代码访问到。出了这个类的{},访问不到了。public,公有。能被当前class 类名{}内访问。也能被其它位置的对象访问。默认不写,在当前class 类名{}中可以访问。当前包中的其它类中也可以访问。出了当前包,就访问不到了get方法和set方法1.get成员变量名()方法:当成员变量是private的时候,用来获取成员变量。1.set成员变量名()方法:当成员变量是private的时候,用来直接改变成员变量。类的实例化:用类来生成对象。类名 变量名 = new 类名();类名 变量名 = new 构造函数;构造函数:必须与类名相同。不能有返回类型。自动被执行。对象new出的来时间自动被执行。一般都是public。先执行成员变量的初始化,在执行成员函数。不写一般也会被系统默认创建。1234567891011121314151617public class gou { //成员变量 private String mingZi = "大黄" ;  private String zhuRen; //成员函数(方法) public String getMingZi() {  return mingZi; } public void setMingZi(String mingZi) { if(mingZi != zhuRen){  this.mingZi = mingZi; }  } public void jiaoHuan(){ System.out.println(mingZi+":旺!旺!旺!"); }}123456public class home { public static void main(String[] args) { gou a = new gou(); a.setMingZi("小黄");     //用set方法修改名字。 System.out.println("小狗的名字是:"+a.getMingZi()); //用get方法获取名字。 a.jiaoHuan();方法的重载:函数名相同,参数不同(数量,类型)。这两个函数就形成了重载。重载与函数返回类型号没有关系,重载只跟函数名和参数有关系。重载了的函数,会自动跟据调用的实参来决定调用哪个函数。除了构造函数可以重载,普通成员函数也可以重载
  • [技术干货] Java8接口的默认方法
    Java8接口的默认方法什么是默认方法,为什么要有默认方法?简单说,就是接口可以有实现方法,而且不需要实现类去实现其方法。只需在方法名前面加个default关键字即可。为什么要有这个特性?首先,之前的接口是个双刃剑,好处是面向抽象而不是面向具体编程,缺陷是,当需要修改接口时候,需要修改全部实现该接口的类,目前的 java 8之前的集合框架没有foreach方法,通常能想到的解决办法是在JDK里给相关的接口添加新的方法及实现。然而,对于已经发布的版本,是没法在给接口添加新方法的同时不影响已有的实现。所以引进的默认方法。他们的目的是为了使接口没有引入与现有的实现不兼容发展。如以下所示,12345public interface Animal {  default void eat() {    System.out.println("animal eat default method");  }}声明了一个接口,里面只有一个默认方法。然后写一个具体的类实现这个接口,12345678910public class Dog implements Animal {  public void sayHi() {    System.out.println("dog");  }    public static void main(String args[]) {    Dog dog = new Dog();    dog.eat();  }}再具体的类里面不是必须重写默认方法,但必须要实现抽象方法。默认方法的多重继承如下所示代码,1234567891011121314151617181920212223242526272829303132333435public interface A {    void doSomething();    default void hello() {    System.out.println("hello world from interface A");  }    default void foo() {    System.out.println("foo from interface A");  }}  interface B extends A {  default void hello() {    System.out.println("hello world from interface B");    A.super.hello();    this.foo();    A.super.foo();  }}  class C implements B, A {    @Override  public void doSomething() {    System.out.println("c object need do something");  }    public static void main(String args[]) {    A obj = new C();    obj.hello();//调用B的方法    obj.doSomething();  }}123456789hello world from interface B hello world from interface A foo from interface A foo from interface A c object need do somethingobj.hello()调用的是B接口中的默认方法。同时在B接口中的默认方法有调用了父接口中的默认方法。我们再来看一个例子,思考一下在多重继承中,如果出现了同名的默认方法,如下所示,123456789101112131415161718192021222324252627public interface D {  default void hello() {    System.out.println("hello world from D");  }}  interface E {  default void hello() {    System.out.println("hello world from E");  }}  class F implements D, E {    @Override  public void hello() {    System.out.println("hello world F class");    D.super.hello();    E.super.hello();  }    public static void main(String args[]) {    F f = new F();    f.hello();  }  }我们需要制定调用哪个接口的默认方法如下,12D.super.hello();E.super.hello();另一个java8的接口默认方法实例:java8新增了接口的默认方法, 也就是说在接口中也可以有实现了, 这个实现方法是默认的实现,你也可以在接口的实现类里对此默认方法进行重写。如下实例:12345678910111213141516171819202122232425262728293031323334353637383940public class AppInterfaceDefaultMethod {    public static interface DefaultMethodDemo {    //定义默认方法, 默认方法前面加default关键字, 后面跟方法声明和方法体    default void demo(String input) {      System.out.println(input);    }      void doSomething();  }    public static class DemoClass implements DefaultMethodDemo {    @Override    public void doSomething() {      System.out.println("do something");    }  }    public static class DemoClassOverrideDemo implements DefaultMethodDemo {    //重写了默认方法    @Override    public void demo(String input) {      System.out.println("demo " + input + " by override method");    }      @Override    public void doSomething() {        System.out.println("do something");    }  }    public static void main(String[] args) {    DefaultMethodDemo demo = new DemoClass();    demo.demo("abc");      DefaultMethodDemo demoOverride = new DemoClassOverrideDemo();    demoOverride.demo("abc");  }}以上就是关于Java8接口的默认方法详细介绍,希望对大家的学习有所帮助。打印结果:
  • [技术干货] java中中英文实现首字母排序
    在Java中对于字符串数组的排序,我们可以使用Arrays.sort(String[])方法很便捷的进行排序。例如:1234567String[] arrays = new String[] { "gyu", "sdf", "zf", "大同", "收到", "地方", "三等分", "的人", "反对高铁", "泛代数", "上的投入", "和国家" };/*设置语言环境*/Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA);Arrays.sort(arrays, com);for (String item:arrays) { System.out.print(item+" ");}输出的结果为:“gyu  sdf  zf  大同  的人  地方  反对高铁  泛代数  和国家  三等分  上的投入  收到”;在Java中排列的顺序是按照数字->英文->汉字进行排序的,这种排序方式可以满足部分要求,但很多情况下我们并不希望这样排列!例如Anroid中的通讯录,音乐播放列表等等,这些情形下我们希望英文首字母和中文拼音首字母一样的排列在一起以方便查询。由于这类排序算法很复杂,例如首字母相同的字符串还要接着比较第二个、第三个...。但是如果我们将jdk自带的排序加以应用就不会显得那么复杂了;我的想法是这样的:既然Java中排序是按数字->英文->汉字来进行排序的,那我们就把每个汉字打头的字符串前面加上一个该字符串第一个字符的拼音的首字母和一个区分符“&”,再使用jdk提供的排序函数进行排序,这时我们得到的就是我们想要的排序的数组了。然后再遍历数组,将包含&符号的字符串去掉&和第一个英文字母便完成了整个排序了,具体实现代码如下(获取汉字拼音需要引用该jar:pinyin4j-2.5.0.jar):12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849/*** 将字符串数字按首字母先后进行排序 * * Java原生排序为 数字->英文->中文 * 为了将英文和中文首字母相同的排列到一起 * 先将字符串首字符为汉字的改为该汉字的首字母加上该字符串 * 为了以示区分中间再加一个分割符& * 然后使用Java原生排序算法 * 再将包含&字符的字符串中的&和首字母去除从而达到排序目的 * */public static void main(String[] args) {  String[] arrays = new String[] { "gyu", "sdf", "zf", "大同", "收到", "地方", "三等分", "的人", "反对高铁", "泛代数", "上的投入", "和国家" }; for (int i = 0; i < arrays.length; i++) {  String str = arrays[i];  if (str.length() == 0)  return;  String alphabet = str.substring(0, 1);  /*判断首字符是否为中文,如果是中文便将首字符拼音的首字母和&符号加在字符串前面*/  if (alphabet.matches("[\\u4e00-\\u9fa5]+")) {  str = getAlphabet(str) + "&" + str;  arrays[i] = str;  } } /*设置排序语言环境*/ Comparator<Object> com = Collator.getInstance(java.util.Locale.CHINA); Arrays.sort(arrays, com); /*遍历数组,去除标识符&及首字母*/ for (int i=0;i<arrays.length;i++) {  String str=arrays[i];  if(str.contains("&")&&str.indexOf("&")==1){  arrays[i]=str.split("&")[1];  }  System.out.println(arrays[i]); } } public static String getAlphabet(String str) { HanyuPinyinOutputFormat defaultFormat = new HanyuPinyinOutputFormat(); // 输出拼音全部小写 defaultFormat.setCaseType(HanyuPinyinCaseType.LOWERCASE); // 不带声调 defaultFormat.setToneType(HanyuPinyinToneType.WITHOUT_TONE); String pinyin = null; try {  pinyin = (String) PinyinHelper.toHanyuPinyinStringArray(str.charAt(0), defaultFormat)[0]; } catch (BadHanyuPinyinOutputFormatCombination e) {  e.printStackTrace(); } return pinyin.substring(0, 1);}这时输出结果为:“大同 的人 地方 反对高铁 泛代数 gyu 和国家 三等分 上的投入 收到 sdf zf”,大家也可以自己尝试自己写排序算法去实现,锻炼一下思维也不无坏处,呵呵。
  • [技术干货] java equals 方法域hashcode方法
    解析1.Object类 的equals 方法复制代码代码如下:   /**     * Indicates whether some other object is "equal to" this one.     * <p>     * The {@code equals} method implements an equivalence relation     * on non-null object references:     * <ul>     * <li>It is <i>reflexive</i>: for any non-null reference value     *     {@code x}, {@code x.equals(x)} should return     *     {@code true}.     * <li>It is <i>symmetric</i>: for any non-null reference values     *     {@code x} and {@code y}, {@code x.equals(y)}     *     should return {@code true} if and only if     *     {@code y.equals(x)} returns {@code true}.     * <li>It is <i>transitive</i>: for any non-null reference values     *     {@code x}, {@code y}, and {@code z}, if     *     {@code x.equals(y)} returns {@code true} and     *     {@code y.equals(z)} returns {@code true}, then     *     {@code x.equals(z)} should return {@code true}.     * <li>It is <i>consistent</i>: for any non-null reference values     *     {@code x} and {@code y}, multiple invocations of     *     {@code x.equals(y)} consistently return {@code true}     *     or consistently return {@code false}, provided no     *     information used in {@code equals} comparisons on the     *     objects is modified.     * <li>For any non-null reference value {@code x},     *     {@code x.equals(null)} should return {@code false}.     * </ul>     * <p>     * The {@code equals} method for class {@code Object} implements     * the most discriminating possible equivalence relation on objects;     * that is, for any non-null reference values {@code x} and     * {@code y}, this method returns {@code true} if and only     * if {@code x} and {@code y} refer to the same object     * ({@code x == y} has the value {@code true}).     * <p>     * Note that it is generally necessary to override the {@code hashCode}     * method whenever this method is overridden, so as to maintain the     * general contract for the {@code hashCode} method, which states     * that equal objects must have equal hash codes.     *     * @param   obj   the reference object with which to compare.     * @return  {@code true} if this object is the same as the obj     *          argument; {@code false} otherwise.     * @see     #hashCode()     * @see     java.util.HashMap     */    public boolean equals(Object obj) {        return (this == obj);    }看代码,Object的equals方法,采用== 进行比较,只是比较对象的引用,如果引用的对象相同,那么就返回true.看注释,Object的equals方法,具有如下特性1.reflexive-自反性  x.equals(x)  return true2.symmetric-对称性x.equals(y)  return truey.equals(x)  return true3.transitive-传递性x.equals(y)  return truey.equals(z)  return truex.equals(z)  return true4.consistent-一致性x.equals(y)  return true //那么不管调用多少次,肯定都是返回true5.与null的比较x.equals(null) return false //对于none-null的x对象,每次必然返回false
  • [技术干货] java打包2
    在进入正题之前,你要先打开我们刚刚做好的jar包看看,多了什么呢,META-INF目录?再看看里面是什么,还有一个MANIFEST.MF文件是不是?用文本编辑器(我这里是UltraEdit)打开它看看:  Manifest-Version: 1.0   Created-By: 1.4.2 (Sun Microsystems Inc.)    就是这样。这里我们对它进行修改,加一句:Main-Class: HelloWorld (在第三行)。这个就是我们之前写的那个类,也就是我们的入口类。也即,  Manifest-Version: 1.0   Created-By: 1.4.2 (Sun Microsystems Inc.)   Main-Class: HelloWorld    接下来,我们在命令提示符里执行:  jar  umf  MANIFEST.MF  app.jar  (应该是hello.jar吧)   这样我们使用了我们自己的MANIFEST.MF文件对原来默认的进行了更新。你不妨可以再进去看看是不是添上了Main-Class: HelloWorld这一句。    (是吗,我怎么没试出来,提示java.io.FileNotFoundException:MANIFEST.MF(系统找不到指定的文件)怎么回事?) Ok,这个最后的一步了,来验证我们做的一切,在命令提示符中输入:  java -jar hello.jar(执行)    出现了什么, Hi, Hello World!    我们再来看看jar文件在tomcat中发布,注意:在tomcat中我们就不能再用jar这种格式,而改war格式,它是专门用于web应用的,其实整个过程下来基本上和jar是类似的:   先准备我们要打包的资源。     找到存放tomcat的webapps目录,进到其中,新建一个文件夹,这里命名为hello,再进去新建WEB-INF文件夹,再进去新建classes文件夹,此时我们也将我们唯一的servlet,HelloWorld.java放到这里,在与classes目录同级下建立一文件web.xml。Ok,目前我们初步建立了一个简单的web应用。    这是HelloWorld.java:     import java.io.*;   import javax.servlet.*;   import javax.servlet.http.*;   public class HelloWorld extends HttpServlet {   public void doGet(HttpServletRequest req, HttpServletResponse res)   throws ServletException, IOException {   res.setContentType("text/html");   PrintWriter out = res.getWriter();   out.println("");   out.println("");   out.println("");   out.println("Hello, World!");   out.println("");   }   }//end here!    对它编译。下面是web.xml:   <?xml version="1.0" encoding="UTF-8"?>   <!DOCTYPE web-app PUBLIC "-//Sun Microsystems, Inc.//DTD Web Application 2.3//EN" "http://java.sun.com/dtd/web-app_2_3.dtd">   <web-app>   <servlet>   <servlet-name>hello</servlet-name>   <servlet-class>HelloWorld</servlet-class>   </servlet>   <servlet-mapping>   <servlet-name>hello</servlet-name>   <url-pattern>/HelloWorld</url-pattern>   </servlet-mapping>   </web-app>  在命令提示符下进到先前创制的hello目录下,执行 jar cvf hello.war * ,我们便得到hello.war。将它拷贝至webapps目录下,ok,来看最后一步,打开tomcat的目录conf中的server.xml,加入:  <Context path="/hello" docBase="hello.war" debug="0" reloadable="true"/>   大功告成!运行它,启动tomcat,后在浏览器中输入http://localhost:8080/hello/HelloWorld,有了吗?   最后,如果你想用ant来完成以上的打包活动,下面就告诉你:   对于jar来说。在build.xml中,  <target name="jar">   <jar destfile="${app_home}/hello.jar">   <fileset dir="${dest}" includes="**"/>   <!--fileset dir="${dest}" includes="**/action.properties"/-->   </jar>   </target>     对于war,  <war warfile="hello.war" webxml="./WEB-INF/web.xml">   <fileset dir="html"/>   <lib dir="lib/">   <exclude name="oracle*.jar"/>   </lib>   <classes dir="build/servlets">   <include name="**/*.class"/>   </classes>   </war>     好了,就这么多,希望对你有点帮助。:)  补充:   jar基本操作:     1. 创建jar文件    jar cf jar-file input-file(s)   c---want to Create a JAR file.   f---want the output to go to a file rather than to stdout.   eg: 1)jar cf myjar.jar query_maintain_insert.htm   2)jar cvf myjar.jar query_maintain_insert.htm   v---Produces verbose(详细的) output.  3)jar cvf myjar.jar query_maintain_insert.htm mydirectory   4)jar cv0f myjar.jar query_maintain_insert.htm mydirectory   0---don't want the JAR file to be compressed.   5)jar cmf MANIFEST.MF myjar.jar yahh.txt   m---Used to include manifest information from an existing manifest file.   6)jar cMf MANIFEST.MF myjar.jar yahh.txt   M---the default manifest file should not be produced.   7)jar cvf myjar.jar *   *---create all contents in current directory.   2. 察看jar文件     jar tf jar-file   t---want to view the Table of contents of the JAR file.   eg: 1)jar vft yahh.jar   v---Produces verbose(详细的) output.    3. 提取jar文件    jar xf jar-file [archived-file(s)]   x---want to extract files from the JAR archive.   eg: 1)jar xf yahh.jar yahh.txt(仅提取文件yahh.txt)  2)jar xf yahh.jar alex/yahhalex.txt(仅提取目录alex下的文件yahhalex.txt)    3)jar xf yahh.jar(提取该jar包中的所有文件或目录)    4. 修改Manifest文件    jar cmf manifest-addition jar-file input-file(s)   m---Used to include manifest information from an existing manifest file.    5. 更新jar文件    jar uf jar-file input-file(s)   u---want to update an existing JAR file.
  • [技术干货] java打包
    jar文件听说过吗,没有?或者陌生!好,没关系,这就是我们的第一站:打包发布。     为什么会有这个玩意呢,首先,这是jar的全称:JavaTM Archive (JAR) file,是的,就是java存档文件。这有点类似zip文件,想一想它是干什么的用的呢,压缩!?没错就是要压缩,将我们原先零散的东西放到一下,重新组织,所有这些目的只有一个:方便!好了,不用管他是怎么压缩的,我们的重点是哪些是我们要压缩的(输入),还有压缩成了什么(输出),进而将它发布(部署)。     那我们的输入(要压缩的东西)主要是class文件,还有辅助的资源(这其中可能有图片,jsp文件,html文件等等)。Jar技术在jdk1.1版本中就已存在,在1.2中又有了增强。接下来说说jar的好处吧,这是官方的描述:安全,快速下载,压缩,猎取包,版本化包,可携。    说了这么多,我们现在开始实施。     先打开命令提示符(win2000或在运行框里执行cmd命令,win98为DOS提示符),输入jar Chelp,然后回车(如果你盘上已经有了jdk1.1或以上版本),看到什么:     用法:jar {ctxu}[vfm0Mi] [jar-文件] [manifest-文件] [-C 目录] 文件名 ...     选项:     -c 创建新的存档  -t 列出存档内容的列表  -x 展开存档中的命名的(或所有的〕文件  -u 更新已存在的存档  -v 生成详细输出到标准输出上  -f 指定存档文件名  -m 包含来自标明文件的标明信息  -0 只存储方式;未用zip压缩格式  -M 不产生所有项的清单(manifest〕文件  -i 为指定的jar文件产生索引信息  -C 改变到指定的目录,并且包含下列文件:    如果一个文件名是一个目录,它将被递归处理。     清单(manifest〕文件名和存档文件名都需要被指定,按'm' 和 'f'标志指定的相同顺序。     示例1:将两个class文件存档到一个名为 'classes.jar' 的存档文件中:  jar cvf classes.jar Foo.class Bar.class    示例2:用一个存在的清单(manifest)文件 'mymanifest' 将 foo/ 目录下的所有文件存档到一个名为 'classes.jar' 的存档文件中:  jar cvfm classes.jar mymanifest -C foo/ .    来个小例子试试看:  我们只有一个HelloWorld,如下:     public class HelloWorld{   public static void main(String[ ] args){   System.out.println(“Hi, Hello World!”);   }   }     将这个java文件存到C盘跟目录下,ok,接下来,  在先前打开的命令提示符下(跳转到C盘提示符下),我们输入javac HelloWorld.java,然后继续输入:jar  cvf  hello.jar  HelloWorld.class,回车后去你的C盘看看,多了什么,没错 hello.jar 。  基本的步骤我们现在都知道了,你可以自己去尝试一下随着jar后面的参数的不同,结果有什么变化。      紧接着我们看看如何运行我们的jar包。   
  • [技术干货] java多线程应用实现方法 4
    代码如下:class Info {public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public synchronized void set(String name, int age){this.name=name;try{Thread.sleep(100);}catch (Exception e) {e.printStackTrace();}this.age=age;}public synchronized void get(){try{Thread.sleep(100);}catch (Exception e) {e.printStackTrace();}System.out.println(this.getName()+"<===>"+this.getAge());}private String name = "Rollen";private int age = 20;}/*** 生产者* */class Producer implements Runnable {private Info info = null;Producer(Info info) {this.info = info;}public void run() {boolean flag = false;for (int i = 0; i < 25; ++i) {if (flag) {this.info.set("Rollen", 20);flag = false;} else {this.info.set("ChunGe", 100);flag = true;}}}}/*** 消费者类* */class Consumer implements Runnable {private Info info = null;public Consumer(Info info) {this.info = info;}public void run() {for (int i = 0; i < 25; ++i) {try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}this.info.get();}}}/*** 测试类* */class hello {public static void main(String[] args) {Info info = new Info();Producer pro = new Producer(info);Consumer con = new Consumer(info);new Thread(pro).start();new Thread(con).start();}}【运行结果】:Rollen<===>20ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100Rollen<===>20ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100ChunGe<===>100从运行结果来看,错乱的问题解决了,现在是Rollen 对应20,ChunGe对于100,但是还是出现了重复读取的问题,也肯定有重复覆盖的问题。如果想解决这个问题,就需要使用Object类帮忙了、,我们可以使用其中的等待和唤醒操作。要完成上面的功能,我们只需要修改Info类饥渴,在其中加上标志位,并且通过判断标志位完成等待和唤醒的操作,代码如下:复制代码代码如下:class Info {public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}public synchronized void set(String name, int age){if(!flag){try{super.wait();}catch (Exception e) {e.printStackTrace();}}this.name=name;try{Thread.sleep(100);}catch (Exception e) {e.printStackTrace();}this.age=age;flag=false;super.notify();}public synchronized void get(){if(flag){try{super.wait();}catch (Exception e) {e.printStackTrace();}}try{Thread.sleep(100);}catch (Exception e) {e.printStackTrace();}System.out.println(this.getName()+"<===>"+this.getAge());flag=true;super.notify();}private String name = "Rollen";private int age = 20;private boolean flag=false;}/*** 生产者* */class Producer implements Runnable {private Info info = null;Producer(Info info) {this.info = info;}public void run() {boolean flag = false;for (int i = 0; i < 25; ++i) {if (flag) {this.info.set("Rollen", 20);flag = false;} else {this.info.set("ChunGe", 100);flag = true;}}}}/*** 消费者类* */class Consumer implements Runnable {private Info info = null;public Consumer(Info info) {this.info = info;}public void run() {for (int i = 0; i < 25; ++i) {try {Thread.sleep(100);} catch (Exception e) {e.printStackTrace();}this.info.get();}}}/*** 测试类* */class hello {public static void main(String[] args) {Info info = new Info();Producer pro = new Producer(info);Consumer con = new Consumer(info);new Thread(pro).start();new Thread(con).start();}}【程序运行结果】:Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20ChunGe<===>100Rollen<===>20
  • [技术干货] java多线程应用实现方法 3
    同步和死锁:【问题引出】:比如说对于买票系统,有下面的代码:复制代码代码如下:/*** @author Rollen-Holt* */class hello implements Runnable {public void run() {for(int i=0;i<10;++i){if(count>0){try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}System.out.println(count--);}}}public static void main(String[] args) {hello he=new hello();Thread h1=new Thread(he);Thread h2=new Thread(he);Thread h3=new Thread(he);h1.start();h2.start();h3.start();}private int count=5;}【运行结果】:543210-1这里出现了-1,显然这个是错的。,应该票数不能为负值。如果想解决这种问题,就需要使用同步。所谓同步就是在统一时间段中只有有一个线程运行,其他的线程必须等到这个线程结束之后才能继续执行。【使用线程同步解决问题】采用同步的话,可以使用同步代码块和同步方法两种来完成。【同步代码块】:语法格式:synchronized(同步对象){//需要同步的代码}但是一般都把当前对象this作为同步对象。比如对于上面的买票的问题,如下:复制代码代码如下:/*** @author Rollen-Holt* */class hello implements Runnable {public void run() {for(int i=0;i<10;++i){synchronized (this) {if(count>0){try{Thread.sleep(1000);}catch(InterruptedException e){e.printStackTrace();}System.out.println(count--);}}}}public static void main(String[] args) {hello he=new hello();Thread h1=new Thread(he);Thread h2=new Thread(he);Thread h3=new Thread(he);h1.start();h2.start();h3.start();}private int count=5;}【运行结果】:(每一秒输出一个结果)54321【同步方法】也可以采用同步方法。语法格式为synchronized 方法返回类型 方法名(参数列表){// 其他代码}现在,我们采用同步方法解决上面的问题。复制代码代码如下:/*** @author Rollen-Holt* */class hello implements Runnable {public void run() {for (int i = 0; i < 10; ++i) {sale();}}public synchronized void sale() {if (count > 0) {try {Thread.sleep(1000);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(count--);}}public static void main(String[] args) {hello he = new hello();Thread h1 = new Thread(he);Thread h2 = new Thread(he);Thread h3 = new Thread(he);h1.start();h2.start();h3.start();}private int count = 5;}【运行结果】(每秒输出一个)54321提醒一下,当多个线程共享一个资源的时候需要进行同步,但是过多的同步可能导致死锁。此处列举经典的生产者和消费者问题。【生产者和消费者问题】先看一段有问题的代码。复制代码代码如下:class Info {public String getName() {return name;}public void setName(String name) {this.name = name;}public int getAge() {return age;}public void setAge(int age) {this.age = age;}private String name = "Rollen";private int age = 20;}/*** 生产者* */class Producer implements Runnable{private Info info=null;Producer(Info info){this.info=info;}public void run(){boolean flag=false;for(int i=0;i<25;++i){if(flag){this.info.setName("Rollen");try{Thread.sleep(100);}catch (Exception e) {e.printStackTrace();}this.info.setAge(20);flag=false;}else{this.info.setName("chunGe");try{Thread.sleep(100);}catch (Exception e) {e.printStackTrace();}this.info.setAge(100);flag=true;}}}}/*** 消费者类* */class Consumer implements Runnable{private Info info=null;public Consumer(Info info){this.info=info;}public void run(){for(int i=0;i<25;++i){try{Thread.sleep(100);}catch (Exception e) {e.printStackTrace();}System.out.println(this.info.getName()+"<---->"+this.info.getAge());}}}/*** 测试类* */class hello{public static void main(String[] args) {Info info=new Info();Producer pro=new Producer(info);Consumer con=new Consumer(info);new Thread(pro).start();new Thread(con).start();}}【运行结果】:Rollen<---->100chunGe<---->20chunGe<---->100Rollen<---->100chunGe<---->20Rollen<---->100Rollen<---->100Rollen<---->100chunGe<---->20chunGe<---->20chunGe<---->20Rollen<---->100chunGe<---->20Rollen<---->100chunGe<---->20Rollen<---->100chunGe<---->20Rollen<---->100chunGe<---->20Rollen<---->100chunGe<---->20Rollen<---->100chunGe<---->20Rollen<---->100chunGe<---->20大家可以从结果中看到,名字和年龄并没有对于。那么如何解决呢?<!--[if !supportLists]-->1) <!--[endif]-->加入同步<!--[if !supportLists]-->2) <!--[endif]-->加入等待和唤醒先来看看加入同步会是如何。
  • [技术干货] java多线程应用实现方法 2
    2关于选择继承Thread还是实现Runnable接口?其实Thread也是实现Runnable接口的:复制代码代码如下:class Thread implements Runnable {//…public void run() {if (target != null) {target.run();}}}其实Thread中的run方法调用的是Runnable接口的run方法。不知道大家发现没有,Thread和Runnable都实现了run方法,这种操作模式其实就是代理模式。关于代理模式,我曾经写过一个小例子呵呵,大家有兴趣的话可以看一下:http://www.cnblogs.com/rollenholt/archive/2011/08/18/2144847.htmlThread和Runnable的区别:如果一个类继承Thread,则不适合资源共享。但是如果实现了Runable接口的话,则很容易的实现资源共享。复制代码代码如下:/*** @author Rollen-Holt 继承Thread类,不能资源共享* */class hello extends Thread {public void run() {for (int i = 0; i < 7; i++) {if (count > 0) {System.out.println("count= " + count--);}}}public static void main(String[] args) {hello h1 = new hello();hello h2 = new hello();hello h3 = new hello();h1.start();h2.start();h3.start();}private int count = 5;}【运行结果】:count= 5count= 4count= 3count= 2count= 1count= 5count= 4count= 3count= 2count= 1count= 5count= 4count= 3count= 2count= 1大家可以想象,如果这个是一个买票系统的话,如果count表示的是车票的数量的话,说明并没有实现资源的共享。我们换为Runnable接口:复制代码代码如下:/*** @author Rollen-Holt 继承Thread类,不能资源共享* */class hello implements Runnable {public void run() {for (int i = 0; i < 7; i++) {if (count > 0) {System.out.println("count= " + count--);}}}public static void main(String[] args) {hello he=new hello();new Thread(he).start();}private int count = 5;}【运行结果】:count= 5count= 4count= 3count= 2count= 1总结一下吧:实现Runnable接口比继承Thread类所具有的优势:1):适合多个相同的程序代码的线程去处理同一个资源2):可以避免java中的单继承的限制3):增加程序的健壮性,代码可以被多个线程共享,代码和数据独立。所以,本人建议大家劲量实现接口。复制代码代码如下:/*** @author Rollen-Holt* 取得线程的名称* */class hello implements Runnable {public void run() {for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName());}}public static void main(String[] args) {hello he = new hello();new Thread(he,"A").start();new Thread(he,"B").start();new Thread(he).start();}}【运行结果】:AAABThread-0Thread-0Thread-0说明如果我们没有指定名字的话,系统自动提供名字。提醒一下大家:main方法其实也是一个线程。在java中所以的线程都是同时启动的,至于什么时候,哪个先执行,完全看谁先得到CPU的资源。在java中,每次程序运行至少启动2个线程。一个是main线程,一个是垃圾收集线程。因为每当使用java命令执行一个类的时候,实际上都会启动一个JVM,每一个jVM实习在就是在操作系统中启动了一个进程。判断线程是否启动复制代码代码如下:/*** @author Rollen-Holt 判断线程是否启动* */class hello implements Runnable {public void run() {for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName());}}public static void main(String[] args) {hello he = new hello();Thread demo = new Thread(he);System.out.println("线程启动之前---》" + demo.isAlive());demo.start();System.out.println("线程启动之后---》" + demo.isAlive());}} 【运行结果】线程启动之前---》false线程启动之后---》trueThread-0Thread-0Thread-0主线程也有可能在子线程结束之前结束。并且子线程不受影响,不会因为主线程的结束而结束。线程的强制执行:复制代码代码如下:/*** @author Rollen-Holt 线程的强制执行* */class hello implements Runnable {public void run() {for (int i = 0; i < 3; i++) {System.out.println(Thread.currentThread().getName());}}public static void main(String[] args) {hello he = new hello();Thread demo = new Thread(he,"线程");demo.start();for(int i=0;i<50;++i){if(i>10){try{demo.join(); //强制执行demo}catch (Exception e) {e.printStackTrace();}}System.out.println("main 线程执行-->"+i);}}}【运行的结果】:main 线程执行-->0main 线程执行-->1main 线程执行-->2main 线程执行-->3main 线程执行-->4main 线程执行-->5main 线程执行-->6main 线程执行-->7main 线程执行-->8main 线程执行-->9main 线程执行-->10线程线程线程main 线程执行-->11main 线程执行-->12main 线程执行-->13...线程的休眠:复制代码代码如下:/*** @author Rollen-Holt 线程的休眠* */class hello implements Runnable {public void run() {for (int i = 0; i < 3; i++) {try {Thread.sleep(2000);} catch (Exception e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName() + i);}}public static void main(String[] args) {hello he = new hello();Thread demo = new Thread(he, "线程");demo.start();}}【运行结果】:(结果每隔2s输出一个)线程0线程1线程2线程的中断:复制代码代码如下:/*** @author Rollen-Holt 线程的中断* */class hello implements Runnable {public void run() {System.out.println("执行run方法");try {Thread.sleep(10000);System.out.println("线程完成休眠");} catch (Exception e) {System.out.println("休眠被打断");return; //返回到程序的调用处}System.out.println("线程正常终止");}public static void main(String[] args) {hello he = new hello();Thread demo = new Thread(he, "线程");demo.start();try{Thread.sleep(2000);}catch (Exception e) {e.printStackTrace();}demo.interrupt(); //2s后中断线程}}【运行结果】:执行run方法休眠被打断在java程序中,只要前台有一个线程在运行,整个java程序进程不会小时,所以此时可以设置一个后台线程,这样即使java进程小时了,此后台线程依然能够继续运行。复制代码代码如下:/*** @author Rollen-Holt 后台线程* */class hello implements Runnable {public void run() {while (true) {System.out.println(Thread.currentThread().getName() + "在运行");}}public static void main(String[] args) {hello he = new hello();Thread demo = new Thread(he, "线程");demo.setDaemon(true);demo.start();}}虽然有一个死循环,但是程序还是可以执行完的。因为在死循环中的线程操作已经设置为后台运行了。线程的优先级:复制代码代码如下:/*** @author Rollen-Holt 线程的优先级* */class hello implements Runnable {public void run() {for(int i=0;i<5;++i){System.out.println(Thread.currentThread().getName()+"运行"+i);}}public static void main(String[] args) {Thread h1=new Thread(new hello(),"A");Thread h2=new Thread(new hello(),"B");Thread h3=new Thread(new hello(),"C");h1.setPriority(8);h2.setPriority(2);h3.setPriority(6);h1.start();h2.start();h3.start();}}【运行结果】:A运行0A运行1A运行2A运行3A运行4B运行0C运行0C运行1C运行2C运行3C运行4B运行1B运行2B运行3B运行4。但是请读者不要误以为优先级越高就先执行。谁先执行还是取决于谁先去的CPU的资源、另外,主线程的优先级是5.线程的礼让。在线程操作中,也可以使用yield()方法,将一个线程的操作暂时交给其他线程执行。复制代码代码如下:/*** @author Rollen-Holt 线程的优先级* */class hello implements Runnable {public void run() {for(int i=0;i<5;++i){System.out.println(Thread.currentThread().getName()+"运行"+i);if(i==3){System.out.println("线程的礼让");Thread.currentThread().yield();}}}public static void main(String[] args) {Thread h1=new Thread(new hello(),"A");Thread h2=new Thread(new hello(),"B");h1.start();h2.start();}}A运行0A运行1A运行2A运行3线程的礼让A运行4B运行0B运行1B运行2B运行3线程的礼让B运行4
  • [技术干货] java多线程应用实现方法
    这一篇文章主要关于java多线程,主要还是以例子来驱动的。因为讲解多线程的书籍和文章已经很多了,所以我也不好意思多说,呵呵、大家可以去参考一些那些书籍。我这个文章主要关于实际的一些问题。同时也算是我以后复习的资料吧,。呵呵大家多多指教。同时希望多结交一些技术上的朋友。谢谢。----------------------------------------------------------------------------------------------------------------------------------------------------java中的多线程在java中要想实现多线程,有两种手段,一种是继续Thread类,另外一种是实现Runable接口。对于直接继承Thread的类来说,代码大致框架是:复制代码代码如下:class 类名 extends Thread{方法1;方法2;…public void run(){// other code…}属性1;属性2;…}先看一个简单的例子:复制代码代码如下:/*** @author Rollen-Holt 继承Thread类,直接调用run方法* */class hello extends Thread {public hello() {}public hello(String name) {this.name = name;}public void run() {for (int i = 0; i < 5; i++) {System.out.println(name + "运行 " + i);}}public static void main(String[] args) {hello h1=new hello("A");hello h2=new hello("B");h1.run();h2.run();}private String name;}【运行结果】:A运行 0A运行 1A运行 2A运行 3A运行 4B运行 0B运行 1B运行 2B运行 3B运行 4我们会发现这些都是顺序执行的,说明我们的调用方法不对,应该调用的是start()方法。当我们把上面的主函数修改为如下所示的时候:复制代码代码如下:public static void main(String[] args) {hello h1=new hello("A");hello h2=new hello("B");h1.start();h2.start();}然后运行程序,输出的可能的结果如下:A运行 0B运行 0B运行 1B运行 2B运行 3B运行 4A运行 1A运行 2A运行 3A运行 4因为需要用到CPU的资源,所以每次的运行结果基本是都不一样的,呵呵。注意:虽然我们在这里调用的是start()方法,但是实际上调用的还是run()方法的主体。那么:为什么我们不能直接调用run()方法呢?我的理解是:线程的运行需要本地操作系统的支持。如果你查看start的源代码的时候,会发现:复制代码代码如下:public synchronized void start() {/*** This method is not invoked for the main method thread or "system"* group threads created/set up by the VM. Any new functionality added* to this method in the future may have to also be added to the VM.** A zero status value corresponds to state "NEW".*/if (threadStatus != 0 || this != me)throw new IllegalThreadStateException();group.add(this);start0();if (stopBeforeStart) {stop0(throwableFromStop);}}private native void start0();注意我用红色加粗的那一条语句,说明此处调用的是start0()。并且这个这个方法用了native关键字,次关键字表示调用本地操作系统的函数。因为多线程的实现需要本地操作系统的支持。但是start方法重复调用的话,会出现java.lang.IllegalThreadStateException异常。通过实现Runnable接口:大致框架是:复制代码代码如下:class 类名 implements Runnable{方法1;方法2;…public void run(){// other code…}属性1;属性2;…}来先看一个小例子吧:复制代码代码如下:/*** @author Rollen-Holt 实现Runnable接口* */class hello implements Runnable {public hello() {}public hello(String name) {this.name = name;}public void run() {for (int i = 0; i < 5; i++) {System.out.println(name + "运行 " + i);}}public static void main(String[] args) {hello h1=new hello("线程A");Thread demo= new Thread(h1);hello h2=new hello("线程B");Thread demo1=new Thread(h2);demo.start();demo1.start();}private String name;}【可能的运行结果】:线程A运行 0线程B运行 0线程B运行 1线程B运行 2线程B运行 3线程B运行 4线程A运行 1线程A运行 2线程A运行 3线程A运行 4
总条数:2294 到第 页
上滑加载中