异常,Object,多线程笔记

异常

一般分为两大类:

1.    一般不可处理的,ERROR

2.    可以处理的,Exception

异常抛出到上一层

 

throw newNullIndexOutBoundsException(“数组越界”);

throw new NullPointException(“空指针异常”);

自定义异常

如果让一个类成为异常类,必须要继承异常体系,因为只有称为异常体系的子类才有资格具有可抛性。

Class  FuShuIndexException extends Exception

{

FuShuIndexException(){

}

}

If(index<0){

thrownew FushuIndexException();

}

异常的分类:

1.编译时被检测异常:只要是Exception和其子类都是,除了特殊子类    RuntimeException体系

2.编译时不检测出异常(运行时):就是Exception中的RuntimeException和其子类

Throws throw的区别

Throws 使用在函数上

Throw使用在函数内

Throws 抛出的是异常类,可以抛出多个,用逗号隔开

Throw抛出的是异常对象

classFuShuExceptionextends Exception

{

      FuShuException(){

          

      }

FuShuException(String meg){

          super(meg);   

      }

}

publicclass YiChang {

     

      publicstaticvoid main(String[] args)throws FuShuException {

          int [] arry =newint [3];

          method(arry,-1);

          

      }

      publicstaticint method(int []a,int index) throws FuShuException{

          if(a==null)

          {

                thrownew NullPointerException("空指针异常");

          }

          if(index >= a.length)

          {

                thrownewArrayIndexOutOfBoundsException("数组越界异常");

          }

          if(index <0)

          {

                thrownew FuShuException("负数异常");

          }

          return a[index];

      }

 

}

Try catch finally

 Finlly 一定为执行的代码,不管你在catch中有没有return

如果有catch中有return则不会执行finally后的代码,而会执行finally中的代码

有一种情况finally不会执行,在catch中有System.exit(0)/退出jvm

 

Try finally   finlly关闭自己开启的资源 try中抛出异常

注意事项:子类抛出异常,父类也要抛出异常或者改异常的子类

如果父类抛出多个异常,子类只能抛出父类异常的子集

Object

判断两个对象是否相等

Equals(Object obj);

getClass是获得的当前对象的字节码文件对象{

         包括,该类的名字,类的属性

}

class Personextends Object

{

      intage;

      String name ;

      Person(Stringname,int age){

          this.name = name;

          this.age = age;

      }

      publicboolean equals(Object obj)

      {

          if(!(objinstanceof Person)){

                thrownew ClassCastException("类型错误");

          }

          Person p= (Person)obj;

          returnthis.age == p.age;

      }

}

publicclass ObjectTest {

 

      publicstaticvoid main(String[] args) {

          Person p1=new Person("j",2);

          Person p2=new Person("j",2);

          System.out.println(p1==p2);//false

          System.out.println(p1.equals(p2));//false

          Person p3= p1;

          System.out.println(p1==p3);//true;

          System.out.println(Integer.toHexString(p1.hashCode()));

          Classc1 = p1.getClass();

          Classc2 = p2.getClass();

          System.out.println(c1==c2);//true

          System.out.println(c1.getName());

          System.out.println(p1);

          System.out.println(p1.getClass().getName()+"@"+Integer.toHexString(p1.hashCode()));

          

      }

 

多线程

进程:正在运行的程序

一个进程可以有多条路径,称之为线程

一个进程至少有一个线程

每一个线程都有自己运行的内容,这个内容称之为线程要执行的任务

 

如何创建线程

1.    定义一个类继承Thread

2.    覆盖Thread类中的run方法

自定义的线程的任务;

Thread 类用于描述线程,线程是需要任务的,所以Thread类对任务的描述。

这个任务就是通过Thread类的run方法来体现,也就是说,run方法就是封装自定义线程运行的任务

Run方法中定义就是线程要运行的任务代码

 

如果线程对象直接调用run方法,则和普通对象一样,只有一个主线程执行

所有当定义线程对象后,调用strart()直接开启线程,自动调用run方法。此时就开启了线程。

调用run方法和start有什么区别

Run虽然有线程,但不会启动该线程,

调用start方法启动线程

可以通过ThreadgetName()获得当前线程的名字。

Thread.currentThread().getName()获得当前进程的名字

package com.sdut.day3;

 

 

class Demoextends Thread

{

      private Stringname;

      Demo(Stringname){

          super(name);

          this.name = name;

      }

      publicvoid show()

      {

          for(int i = 0 ;i<10 ;i++)

          {

                

                System.out.println("线程"+name+i+"线程名字"+getName());//问题getName()是获得当前进程的名字,

                                                                                                                                                           //Thread.currentThread().getName()也是获得当前进程的名字,二者有啥区别

          }

      }

      publicvoid run()

      {

          show();

      }

     

     

}

publicclass ThreadDemo {

 

      /**

       * @param args

       */

      publicstaticvoid main(String[] args) {

          Demo d1 =new Demo("第一");

          Demo d2 =new Demo("第二");//线程

          d1.start();

          d2.start();

      }

 

}

 

创建线程

线程的开始:start()

线程的结束:stop()方法

线程的冻结sleep(time)自动醒过来

Wait()方法使线程冻结,通过notify()来唤醒进程

Cpu的执行资格:可以被cpu处理,在处理队列中等待

Cpu的执行权:正在被cpu处理

冻结:释放执行权的同时,释放执行资格

临时阻塞状态:具备执行资格,单不具备执行权,等待执行权

Stop()

总结:线程先创建====start()=====线程的执行============线程的销毁

 

线程的阻塞

Sleep()

 

 

 

 

 


                                                                     线程的冻结

 

 

线程创建的第二种方式:实现Runnable

1.覆盖接口中的run方法,将线程的任务封装到run方法中

2.通过Thread类创建线程对象,并将Runnable接口的子类对象作为Thread类的构造函数的参数进行传递

为什么:

因为线程的任务都封装在Runnablerun方法中,所以在线程对象创建时就必须明确要运行的任务

3.      调用线程对象的start()方法开启线程

4.      如果不传递,则是Thread的默认任务,传的话则是自己指定的。

5.    /*

6.     *第二种实现Runnable接口来创建对象的具体过程总结

7.     *class Thread implements Runnable

8.     * {

9.     *        private Runnable r1 ;

10.  *            Thread(){

11.  *            }

12.  *            Thread(Runnable r){

13.  *             r1 =  r

14.  * }

15.  *            public void run()

16.  *            {

17.  *                  r1.run();

18.  *            }

19.  *            public void start()

20.  *            {

21.  *                  run()

22.  *            }

23.  * }

24.  *class Demo implements

25.  *{

26.  *    public void run()

27.  *{

28.  *        System.out.println("ddd");

29.  *}

30.  *}

31.  *class Test()

32.  *{

33.  *        public static void main(String []args){

34.  *        Demo d = new Demo();

35.  *        Thread t = new Thread(d);//通过此处把d穿进去,利用多态,为构成方法初始化

36.  *此时Thread类中的r就是d Runnable r =  new Demo()//向上转型

37.  *

38.  *        t.start() ;//调用start()方法时,会调用run()方法,在调用r.run()即子类的run方法,因为

39.  *多态执行看右边

40.  *}

41.  *}

42.  * */

实现Runnable的好处

1.       将线程的任务从线程的子类中分离出来,进行了单独的封装。

按照面向对象的思想将任务封装成对象

2.       避免了java的单继承的局限性

线程的安全性问题

/

class Ticketimplements Runnable

{

      private intnum = 1;

      publicvoid run()

      {

          sale();

      }

      publicvoid sale()

      {

          while(true){

                if(num>0)

                {

                     System.out.println(Thread.currentThread().getName()+"--------sale"+num--);

                }

          }

      }

}

publicclass ThreadDemo2 {

 

      publicstaticvoid main(String[] args) {

          Ticket s=new Ticket();//线程任务对象的封装

          Thread  t1=new Thread(s);

          Thread  t2=new Thread(s);

          Thread  t3=new Thread(s);

          t1.start();

          t2.start();

          t3.start();

          

      }

 

}

当第一个线程进入if(num>0)判断,此时num=1进入if里面

当进入里面后,cpu切换到别的线程,此时num=1也进入if里面

同理,其他的进程也能进入if里面

这样输出:就是0 -1 结果明显有错

原因:

1.    多个线程在操作共享数据。

2.    操作共享数据的线程代码有多条

3.    当一个线程在执行操作共享数据的多条代码中,其他进程参与了运算。就会导致线程安全问题的产生。

解决:就是将多条操作共享数据的线程代码封装起来,当有线程在执行这些代码的时候,其他线程不可以参与运算的

用同步代码块。

格式:synchroized(){需要被同步的代码}

 

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
CountDownLatch 可以用于多线程场景中获取线程的执行结果。可以通过以下步骤实现: 1. 创建一个 CountDownLatch 对象,并将计数器初始化为线程数量加1,即 latch = new CountDownLatch(n+1),其中 n 为线程的数量。 2. 创建多个线程,并将 CountDownLatch 对象作为参数传递给这些线程。在每个线程中,执行需要返回结果的操作,并将结果保存在相应的变量中。 3. 在每个线程执行完操作后,调用 countDown() 方法通知 CountDownLatch 对象一个线程已经完成。 4. 在主线程中,调用 await() 方法等待所有线程执行完操作。 5. 当所有线程都执行完操作后,主线程就可以通过获取各个线程保存的结果来进行进一步的处理。 示例代码如下所示: ``` // 创建 CountDownLatch 对象并初始化计数器 CountDownLatch latch = new CountDownLatch(n+1); List<Object> results = new ArrayList<>(); for (int i = 0; i < n; i++) { Thread thread = new MyThread(latch, i, results); thread.start(); } try { // 等待所有线程执行完操作 latch.await(); } catch (InterruptedException e) { e.printStackTrace(); } // 在这里可以对结果进行进一步处理 // results 中保存了每个线程执行的结果 ``` 在上面的代码中,MyThread 是一个自定义的线程,它接受一个 CountDownLatch 对象、线程的编号和一个保存结果的列表作为参数。在 MyThread 的 run() 方法中,执行需要返回结果的操作,并将结果保存在列表中。在操作执行完成后,调用 countDown() 方法通知 CountDownLatch 对象一个线程已经完成。主线程在调用 await() 方法后会等待所有线程执行完操作,然后可以通过获取 results 列表中的结果来进行进一步的处理。<span class="em">1</span><span class="em">2</span><span class="em">3</span> #### 引用[.reference_title] - *1* *3* [【多线程笔记01】多线程之CountDownLatch介绍及其使用](https://blog.csdn.net/qq_39826207/article/details/127113320)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] - *2* [java多线程怎么同步返回结果](https://blog.csdn.net/kkevin_zzhang/article/details/129672820)[target="_blank" data-report-click={"spm":"1018.2226.3001.9630","extra":{"utm_source":"vip_chatgpt_common_search_pc_result","utm_medium":"distribute.pc_search_result.none-task-cask-2~all~insert_cask~default-1-null.142^v92^chatsearchT3_1"}}] [.reference_item style="max-width: 50%"] [ .reference_list ]

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值