您的位置:首页 > 编程语言 > Java开发

java多线程复习转载

2012-10-28 22:12 218 查看
1 .finally 语句:这个代码块中定义的是一定会执行的代码。

不能被catch块中的return语句结束,可是能被System.exit(0)结束。

2.主要用于关闭资源,只要使用了资源,就一定要将其关闭。

3.应用:数据库的连接,连接——操作——关闭。可能在操作过程中出现异常,没关闭数据库,就需要把关闭数据库放在finally语句里面。
2 组合方式:

try{}catch (){}、try{}catch(){}、try{}finally{}(这种用于关闭资源)

3 .异常在覆盖时的细节

1.子类在覆盖父类方法时,如果父类方法抛出了异常,子类覆盖的方法只能抛出父类方法异常或其子类。
2.父类方法如果抛出多个异常,子类在覆盖父类方法时,只能抛出父类异常的子集。
3.如果父类中的方法没有抛出异常,子类覆盖父类时,绝对不能声明异常。只能进行 try{} catch 处理;如果处理不了,那就应该让程序

停掉,让调用者知道。即在catch中抛出RuntimeException异常或其子类对象,这时不用抛,RuntimeException不用在函数上声明。

包(package):包名具有唯一性 在windows中的具体体现:文件夹。

包的作用:1.分类管理类文件;

2.对类提供了多层名称空间。

2.如何定义:使用关键字 package,定义必须定义在源代码的第一行,类名的全称是:包名.类名;

包名全小写如mypackage.

3.步骤:1.javac -d 包的路径 全类名.java

2.set classpath=包的路径;

3.java 包名.类名
一个包中不能存在两个public修饰的类。

被访问的包中,类和方法都需要被public修饰,否则权限不够。

4.包与包之间的继承

protected:包的修饰符,保护权限,只有子类才能用;用于保护父类中的成员。

四种权限: public protected default(默认的) private

同一个类中: ok ok ok ok

同一个包中: ok ok ok

子类: ok ok

不同包中: ok

5.简化书写:使用import关键字导入,格式:import 全类名;导入的都是包中的类;若是需要导入多个类,则使用通配符,如 import packa.*。而在真实开发时,用到哪个则导入哪个,根本也用不到导入,用高级编辑器。

6.注意:

1.import packa.* :只导入packa包的当前目录下的所有类,而不导入当前目录下的包。

2.当导入的包中的类有重名时,使用该类时,必须用包名.类名的全名称,否则无法区分,会产生使用的不确定性。

如 import packa.Demo;

import packb.Demo;

不能new Demo(),而需new packa.Demo();

5 Jar包:java的压缩包。

-c:创建新的归档文件

-x:解压

java压缩工具:jar cvf haha.jar pack

6 多线程技术

1.进程:正在进行中的程序。

2.线程(Thread):负责进程进行执行。一个进程至少有一个线程,若有多个则称为多线程程序;线程也可以称为执行线程、执行路径、执行背景。

3.好处:可以同时执行多个程序。

4.JVM多线程的基本体现:

JVM也是多线程,至少有一个主线程和垃圾回收线程。主线程执行的是主函数中的内容,垃圾回收线程执行的对堆内存进行内存释放的代码。

5.垃圾回收的方法:finalize(),垃圾回收

gc():运行垃圾回收器,System.gc();启动后不一定立即执行,因为CPU在随机做着切换,先切换到哪就先执行哪个。

6.自定义线程:通过APIThread类的查阅,两种方式:

1.继承Thread类,覆写run()方法,创建Thread子类对象,调用start方法来开启线程并调用run方法;线程类在描述线程时,有一个功能函数run,专门用于封装执行的任务


主线程也是同理,该线程执行的任务在主函数中。

Thread t=new Thread();创建进程。

1.覆写run方法的原因:创建进程的目的是为了运行指定的代码,任务就应该自己指定。

2.特定方法start():开启线程并调用run方法运行线程。

start和run区别:调用run方法,并没有开启新的线程,都是由主线程来执行,无法完成同时运行的需求;

调用start方法,开启了新的线程并调用了线程的任务方法run方法,实现了代码同时执行。

3.执行路径是在每一条路径上先进后出的,即每个线程都有自己单独的一片栈内存空间。

4.currentThread():返回当前正在执行的进程,Thread.currentThread().getName();结果是Thread-编号,编号从0开始。
5.线程是分区来进行管理的,当前线程发生异常只影响当前线程,不影响其它线程。

6.主线程是最后结束的线程,只要还有存活的线程,它就不能结束。

第二种:实现Runnable接口,见第十二天日志

创建线程的目的:为了开辟一个执行路径去执行指定的代码,让其和其它代码同时运行;意味着每一个线程的创建都有自己要运行的内容,而这个内容也称为线程的任务。

线程的四种状态:被创建、运行、冻结notify、sleep、wait、消亡(还有一个特殊状态:就绪)

被创建:start();

运行:具备执行资格,同时具备执行权

冻结:sleep(time), wait()---notify()唤醒;线程释放了执行权,同时释放资格。

临时阻塞状态:线程具备CPU的执行资格,没有CPU的执行权

消亡:stop()
 

创建线程的第一种方式是:
1,继承Thread,//** extends Thread

2,复写run方法,将线程要运行的任务代码存储到run方法中。//public void run(){}

3,创建Thread类的子类对象。Ticket t = new Ticket(); Thead t1 = new Thread()

4,调用start方法开启线程并调用run方法。t1.start()

创建线程的第二种

1,定义类实现Runnable接口

2. 覆盖该接口中的run()方法

3,通过Thread类创建线程对象,

4,将实现Runnable接口的实现类的对象作为参数传递给Thread类的构造函数

将run方法所属的对象传递给线程,让线程去运行指定的对象 的run 方法。

5,调用Thread类的start 方法开启线程

Runnable接口的好处:

避免了单继承的局限性

Runnable接口的出现 ,更是按照面向对象的思想,将线程要运行的任务进行单独的封装,

降低了线程对象和线程任务的耦合性。

class Demo extends Thread{//第一种

public viod run(){}

}
Demo d1 = new Demo();

Demo d2 = new Demo();//线程对象和线程的耦合性强
//将线程任务进行描述

class Demo implements Runnable{//第二种

public void run(){}

}
class Demo2 implements Runable{

public void run(){

}

}
Demo d = new Demo();//将线程任务封闭成对象
Demo2 d2 = new Demo2();

Thread t = new Thread(d2);//通过线程对象的构造函数和任务相关联
创建线程,建议使用第二种方式。
class Demo implements Runnable{

//将线程要运行的任务代码封装到了run方法中

public void run(){

for(int x=1; x<=20; x++){

System.out.println(Thread.currentThread().getName()+"..."+x);

}

}

}
class ThreadDemo4{

public static void main(String args[]){

Demo d=new Demo();
//创建线程对象。因为没有了Thread的子类 ,所以通过Thread类来完成线程对象的创建。

Thread t1=new Thread(d);

Thread t2=new Thread(d);

t1.start();//开启了线程并调用了线程中的run方法。只不过线程类中的run方法并没有定义我们要让线程运行的内容。

t2.start();

}

}
第一种方式

class Demo extends Thread{

//覆盖Thread类中的run方法,将线程任务代码封装到该方法中。

public void run(){

for(int x=1; x<=20; x++){

System.out.println(Thread.currentThread().getName()+"...extends..."+x;

}

}

}

创建线程,建议使用第二种方法

多线程的安全问题
对安全问题的分析:

1,多个线程在处理同一个共享数据

2, 线程任务代码中有多条语句在操作这个共享数据

3,这些多条操作共享数据的语句被多个线程分开进行执行

也就是说,在一个线程执行这些语句的过程中,其它线程参与了运算,导致数据的错误
总结: 线程任务代码中只要存在着:

1,共享数据

2 多条操作共享数据的语句

就容易产生多线程的安全问题

解决线程安全问题的原理:

将多条操作共享数据代码进行封装,

在某一时刻,只能一个线程在内运行,在运行期间,其它的线程都进不来

只有这个线程运行完,其它线程才有机会执行其中的内容

怎样封装呢?

JAVA中提供了一个用于封闭的代码块,就是同步代码块

synchronized(obj)//这个obj对象可以是任意的

{

}
synchronized synchronized//相当于一个锁 举例:火车上的卫生间

为了给同步代码块指定一个对象,可以用自定义的,也可以用已有的

如object

同步的好处:解决了多线程的安全问题
当程序中出现了多线程的安全问题时,加入了同步进行解决,却发现问题依旧,

你可以先明确一下同步的前提
同步的前提:

必须有多个线程,而且使用的是同一个锁。

同步的弊端:降低了效率。容易出现死锁

class Ticket implements Runnable{

private int num = 100;

private Object obj = new Object();

public void run(){

while(true){

synchronized(obj){

if (num>0)

try{Thread.sleep(10)}

catch(InterruptedException e){

e.getMessage()}//让线程在这里小睡一下

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

}

}

}

}

class TicketDemo2{

public static void main(String args){

Ticket t = new Ticet();

Thread t1 = new Thread(t);

Thread t2 = new Thread(t);

Thread t3 = new Thread(t);

Thread t4 = new Thread(t);

t1.start();

t2.start();

t3.start();

t4.strt();

}

}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: