Java基础重点回顾


 线程
     线程是程序执行的一条路径, 一个进程中可以包含多条线程
     多线程并发执行可以提高程序的效率, 可以同时完成多项工作

多线程实现的两种方式

一种是继承Thread:

public class Demo2_Thread {
		
				/**
				 * @param args
				 */
				public static void main(String[] args) {
					MyThread mt = new MyThread();							//4,创建自定义类的对象
					mt.start();									//5,开启线程
					
					for(int i = 0; i < 3000; i++) {
						System.out.println("bb");
					}
				}
			
			}
			class MyThread extends Thread {									//1,定义类继承Thread
				public void run() {									//2,重写run方法
					for(int i = 0; i < 3000; i++) {							//3,将要执行的代码,写在run方法中
						System.out.println("进黑马好艰难");
					}
				}
			}
另一种是实现Runnable接口

public class Demo3_Runnable {
				/**
				 * @param args
				 */
				public static void main(String[] args) {
					MyRunnable mr = new MyRunnable();					//4,创建自定义类对象
					//Runnable target = new MyRunnable();
					Thread t = new Thread(mr);						//5,将其当作参数传递给Thread的构造函数
					t.start();								//6,开启线程
					
					for(int i = 0; i < 3000; i++) {
						System.out.println("bb");
					}
				}
			}
			
			class MyRunnable implements Runnable {							//1,自定义类实现Runnable接口
				@Override
				public void run() {								//2,重写run方法
					for(int i = 0; i < 3000; i++) {						//3,将要执行的代码,写在run方法中
						System.out.println("进黑马进黑马");
					}
				}
				
			}

这两种方式的区别

 查看源码的区别:
    继承Thread : 由于子类重写了Thread类的run(), 当调用start()时, 直接找子类的run()方法
    实现Runnable : 构造函数中传入了Runnable的引用, 成员变量记住了它, start()调用run()方法时内部判断成员变量Runnable的引用是否为空, 不为空编译时看的是Runnable的run(),运行时执行的是子类的run()方法
    
 继承Thread
     好处是:可以直接使用Thread类中的方法,代码简单
     弊端是:如果已经有了父类,就不能用这种方法
 实现Runnable接口
     好处是:即使自己定义的线程类有了父类也没关系,因为有了父类也可以实现接口,而且接口是可以多实现的
     弊端是:不能直接使用Thread中的方法需要先获取到线程对象后,才能得到Thread的方法,代码复杂

 多线程并发操作同一数据时, 就有可能出现线程安全问题
 使用同步技术可以解决这种问题, 把操作数据的代码进行同步, 不要多个线程一起操作

 通信
     多个线程并发执行时, 在默认情况下CPU是随机切换线程的
     如果我们希望他们有规律的执行, 就可以使用通信, 例如每个线程执行一次打印
怎么通信
     如果希望线程等待, 就调用wait()
     如果希望唤醒等待的线程, 就调用notify();

     notifyAll()方法是唤醒所有线程
     这两个方法必须在同步代码中执行, 并且使用同步锁对象来调用

 什么是适配器
     在使用监听器的时候, 需要定义一个类事件监听器接口.
     通常接口中有多个方法, 而程序中不一定所有的都用到, 但又必须重写, 这很繁琐.
     适配器简化了这些操作, 我们定义监听器时只要继承适配器, 然后重写需要的方法即可.
适配器原理
     适配器就是一个类, 实现了监听器接口, 所有抽象方法都重写了, 但是方法全是空的.类设为抽象 ,不让其他类创建本类对象调用本类方法,没有私有构造,为了让子类重写本类方法。
    目的就是为了简化程序员的操作, 定义监听器时继承适配器, 只重写需要的方法就可以了.

 什么情况下需要同步
     当多线程并发, 有多段代码同时执行时, 我们希望某一段代码执行的过程中CPU不要切换到其他线程工作. 这时就需要同步.
     如果两段代码是同步的, 那么同一时间只能执行一段, 在一段代码没执行结束之前, 不会执行另外一段代码.
同步代码块
     使用synchronized关键字加上一个锁对象来定义一段代码, 这就叫同步代码块
     多个同步代码块如果使用相同的锁对象, 那么他们就是同步的

class Printer {
				Demo d = new Demo();
				public static void print1() {
					synchronized(d){			//锁对象可以是任意对象,但是被锁的代码需要保证是同一把锁,不能用匿名对象
						System.out.print("黑");
						System.out.print("马");
						System.out.print("程");
						System.out.print("序");
						System.out.print("员");
						System.out.print("\r\n");
					}
				}
	
				public static void print2() {	
					synchronized(d){	
						System.out.print("我");
						System.out.print("来");
						System.out.print("了");
						System.out.print("啊");
						System.out.print("\r\n");
					}
				}
			}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值