Java4Android by mars (35--40)学习笔记


35.内部类
一个类定义在另一个类的里面
public class A {
	class B{
		
	}
}
编译之后会生成 A.class和 A$B.class  ( 外部类$内部类.class)

生成内部类的对象 (首先生成一个外部类的对象,然后.new 内部类)

A a = new A();
	
	A.B b = new A().new B();//内部类的名字是 外部类.内部类

还可以用a来生成内部类的对象

    A.B b = a.new B();  

内部类可以随意使用外部类所定义的成员变量和成员函数。但并不意味着内部类继承了外部类的成员变量和成员函数


public class A {
	int i;
	
	class B{
		
		int j;
		
		int funB(){
			int result = i + j;
     //相当于int result = A.this.i + this.j;
			return result;
		}
		
	}
}
匿名内部类
1.定义一个接口A.java


public interface A {
void doSomething();
}
2.B类中成员函数需要A类型的对象作为参数
public class B {
	public void fun(A a){
		System.out.println("B的fun函数");
		a.doSomething();
	}
}
3. new A(){
因为A是接口,不能生成对象。所以紧跟{  }用来实现A接口的 抽象函数(复写A中的抽象方法)
}    

public class Test {
public static void main(String args[]){
	
    B b =  new B();

    b.fun(new A(){

    	public void doSomething(){
    		System.out.println("A接口的实现");
    	}
    	
    });
	
}
}
new A(){ .... }  之后就相当于生成了 实现A接口的匿名类 的对象  (不用再写一个 class implements A来实现)
运行结果      


36.Java当中的线程(一)  多进程 多线程

多进程:在操作系统中能(同时)运行多个任务(程序)
多线程:在同一应用程序中有多个顺序流(同时)执行
线程是进程当中的一个程序执行流程

一般来说,一个软件就相当于一个进程,进程下面又有多个线程




创建线程的方法(一)
(一)定义一个线程类,继承Thread(由JDK提供)并重写其中的run()。run()方法被称为线程体。
由于Java只支持单继承,用这种方法定义的类不能再继承其他类。


public class FirstThread extends Thread {
	
	public void run(){
		for(int i = 0;i<100;i++){
			System.out.println("FirstThread-->"+ i);
		}
			
	}
	
}
注意启动线程用 start() 方法,而不是调用run()方法。如果调用run()就不是启动一个新线程,而是只有一个主线程。

public class Test {
public static void main(String args[]){
	
	//生成线程类的对象
	FirstThread ft =  new FirstThread();
   //启动线程
	ft.start();
   //不能写成ft.run()。如果调用ft.run()会顺序执行run()代码,执行完后再顺序往下执行
	
	for(int i = 0;i<100;i++){
		System.out.println("MainThread-->"+ i);
	}
}
}
其中共有3个线程:主函数是一个线程, ft是第二个线程,还有垃圾回收这个线程

运行结果

37. Java当中的线程(二)
实现线程的方法(二)
(二)提供一个实现接口Runnable的类 作为线程的目标对象,在初始化一个Thread类或者Thread子类的线程对象时,把目标对象传递给这个线程实例,由该目标对象提供线程体


public class  RunnableImpl implements Runnable{
	public void run(){
		for(int i = 0;i<100;i++){
			System.out.println("RunnableImplement-->"+ i);
		}
	}
}
public class Test {
public static void main(String args[]){
	 //生成一个Runnable接口实现类的对象
	 RunnableImpl ri = new RunnableImpl();
	 //生成一个Thread对象,并将Runnable接口实现类的对象作为参数传递给该Thread对象
	 Thread t = new Thread(ri);
	 //通知Thread对象,执行start方法
	 t.start();
}
}
实际开发中,使用接口实现Runnable 这种方法 ,能不用继承就不用继承,毕竟Java只支持单继承

还可以用匿名内部类来实现,注意到Runnable是一个接口。效果是一样的


Thread m = new Thread(new Runnable(){
		 
		 public void run(){
			 
			 for(int i = 0;i<100;i++){
			  System.out.println("RunnableImplement-->"+ i);
		 }
			 }
		 
	 });
	 
	 m.start();
	 
线程的简单控制方法

1.Thread.sleep()  线程休眠(在休眠时,线程处于阻塞状态)


Thread.sleep(2000);
//sleep()是静态方法,而且会产生check 异常
//线程休眠2000毫秒。休眠过后,线程不会马上运行,而是会转入就绪状态,抢占CPU,抢占到CPU之后才会//执行。

public class  RunnableImpl implements Runnable{
	public void run(){
		for(int i = 0;i<100;i++){
			System.out.println("RunnableImplement-->"+ i);
			
			if(i == 50){
				try{
					Thread.sleep(2000);
					
				}catch(Exception e){
					e.printStackTrace();
					
				}
				
			}
		}
	}
}
2.Thread.yield()    一旦运行到这个代码,会让当前线程让出CPU。
注意: 不是说让出CPU就会让其他线程来执行。比如A线程运行到yield(),A线程就让出CPU,之后会和其他线程再次一起抢占CPU.谁抢到CPU谁就执行,可能还是A再次抢到CPU

3.getPriority() , setPriority()  优先级
线程优先级最大是10,最小是1,默认是5
线程优先级越大,执行概率就越大,(将线程优先级设为最大,并不是一定会执行,只是执行概率大)


  Thread t = new Thread(ri);
	 t.setPriority(Thread.MAX_PRIORITY);//设置最大优先级
	// t.setPriority(Thread.MIN_PRIORITY);//最小优先级
	 System.out.println(t.getPriority());

38.Java当中的线程(三)

每一个线程都有名字,可以通过Thread对象的setName()方法设置线程名字,也可以使用getName()方法获取线程的名字


public class Test {
public static void main(String args[]){
   MyThread mt = new MyThread();
   //两个Thread对象,但是这两个Thread对象共用同一个线程体
   Thread t1 = new Thread(mt);
   Thread t2 = new Thread(mt);
   
   t1.setName("a");
   t2.setName("b");
   
//分别启动两个线程
   t1.start();
   t2.start();
}
}

数据安全问题

public class MyThread implements Runnable {
	int i = 100;
	public void run(){
		
		while(true){
//Thread.currentThread() //Thread中的静态方法,返回当前正在执行这段代码的线程
			System.out.println(Thread.currentThread().getName() + i);
		
		i--;
		Thread.yield();
		if(i<0){
			break;
		}
		}
		
	}
}
使用同步代码块  synchronized(this){  }   this指mt这 MyThread 类的对象


public class MyThread implements Runnable {
	int i = 100;
	public void run(){
		
		while(true){
			
		synchronized(this){
			System.out.println(Thread.currentThread().getName() + i);
		
		i--;
		Thread.yield();
		
		
		if(i<0){
			break;
		}
	  }
		
		
		}
	}
}
39.深入同步语法  synchronized 

1.Service.java  包含了fun1() , fun2()。都使用了同步代码块synchronized(this){ .. }


public class Service {
	public void fun1(){
		synchronized(this){
			try{
				Thread.sleep(3*1000);
			}catch(Exception e){
				e.printStackTrace();
				
			}
			
			System.out.println("fun1");
			
		}
		
	}
	
	public void fun2(){
		synchronized(this){
			System.out.println("fun2");
		}	
	}	
}
2. MyThread1 , Mythread2 调用fun1(),fun2()

public class MyThread1 implements Runnable {
  private Service service;
  
  public MyThread1(Service service){
	  this.service = service;
	  
  }
	public void run(){
		service.fun1();
	}
}

public class Mythread2 implements Runnable{
	private Service service;
	  
	  public Mythread2(Service service){
		  this.service = service;
		  
	  }
		public void run(){
			service.fun2();
		}
}
3.Test.java


public class Test {
public static void main(String args[]){
   //整个应用程序中只有一个service对象
	Service service = new Service();
  
	Thread t1 = new Thread(new MyThread1(service) );
	Thread t2 = new Thread(new Mythread2(service) );
	 
	t1.start();
	t2.start();
}
}
运行结果
   

结果分析: 首先启动了t1.start() , 执行fun1()这个方法。fun1()中的synchronized (this),this指的是调用fun1()的这个对象,即在主函数中生成的service

 
 
Service service = new Service();
t1拿到这个对象锁之后开始休眠,t1休眠可能使t2开始执行。t2执行fun2(),但由于fun2()中synchronized (this)还是使用的service做锁
 
  
Thread t1 = new Thread(new MyThread1(service) );
Thread t2 = new Thread(new Mythread2(service) );
现在t1持有这个锁,t2就无法执行
由于锁住了对象service,所以导致t2也无法执行。只有等t1释放锁之后,t2才会执行。


同步锁锁住的是代码块 这个说法错误。 

一旦某一线程获得一个对象的同步锁,那么这个对象上所有被同步的代码 其他的线程都不能执行,都需要等待同步锁被释放之后才能执行。但是不会影响非同步的代码 

public void fun2(){
		//synchronized(this){
			System.out.println("fun2");
		//}
		
	}
注释掉fun2()中同步代码后
运行结果为

同步方法 在返回值前面加上synchronized 
同步方法锁住的是this (调用这个函数的对象) ,跟同步代码块类似,只不过同步代码块可以指定锁住的是哪一个对象,而同步方法锁住的只能是this 


public class Service {
	public synchronized void fun1(){
		
			try{
				Thread.sleep(3*1000);
			}catch(Exception e){
				e.printStackTrace();
				
			}
			
			System.out.println("fun1");
			
	}
	
	public synchronized void fun2(){
		//synchronized(this){
			System.out.println("fun2");
		//}
		
	}
	
	
}


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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值