一、线程(Thread类)
1、概念
进程:运行中的程序。一个程序在运行期间至少会开启一个进程;
线程:一个进程中可以有多个线程,线程就是程序运行的一条路径。
CPU在同一时间只能为一条线程工作,CPU在各个线程之间快速切换。
多线程下载速度快的原因:N个用户连接服务器,如果一个用户开启多个线程连接服务器,占用服务器的CPU更多的资源,服务器在这个用户的线程上工作的时间越长,下载越快。
2、开启新线程的方法
(1)继承Thread类
class MyThread extends Thread { a.定义一个类继承Thread方法
public void run( ) { b.重写run方法,将新线程做的事写在run方法中
……}
}
class ThreadDemo {
public static void main(String[] args) {
MyThread mt = new MyThread( ); c.创建线程对象
mt.start( ); d.开启新线程”对象名.start()”,新线程上自动调用run()方法
}
}
(2)实现Runnable接口
class MyRunnable implements Runnable { a.定义一个类实现Runnable接口
public void run( ) { b.重写run()方法,将新线程要做的事写在run()方法中
……}
}
class MyRunnableDemo {
public static voidmain(String [] args) {
MyRunnable mr = new MyRunnable( );c.创建自定义的Runnable子类对象
Thread t = new Thread(mr); d.创建Thread对象,将子类对象作为参数
传进Thread的构造函数
t.start( ); e.调用start()方法开启新线程
}
}
(3)使用匿名内部类的形式开启新线程
A. 定义Thread的子类对象,调用start( )方法
newThread( ){
public void run( ) {
…………
}
}.start();
B. 定义Runnable接口的实现类,作为参数传入Thread的构造函数,调用start()方法
newThread(new Runnable( ) {
public void run( ) {
……
}
}).start();
3、Thread类的常用方法:
(1) Thread t = Thread.currentThread(); // 获取当前正在执行的线程对象的引用
(2) String getName( ); //获取当前线程的名字
String name = t.getName( );
String name = this.getName( ); 如果线程对象是Thread类的子类,可写成this
(3)String setName(String name); //设置线程的名字。线程开始前后都可以设置
A.创建线程时指定名字:Thread t =new Thread(“线程1”);
B.Thread t = Thread.currentThread( );
t.setName( );
(4)static void sleep(long millis); //控制当前线程休眠
Thread.sleep(3000); //让当前正在执行的线程休眠3000毫秒
注意:a.如果当前类是Thread的子类,可以直接写sleep(3000).
b. run( )方法不能抛异常,只能抓异常。因为run()方法是重写Thread和Runnable类的,而这两个类没有抛出异常。
(5)void setDaemon(boolean b); // 设置当前线程为守护线程,守护线程不单独执行
例如:t2.setDaemon(true); 将t2线程设置为守护线程
(6)t1.join(); // 加入线程。当前线程暂停,等待t1运行结束之后再继续执行。
二、同步
同步是指多个线程可以同时访问一个对象。多线程并发操作同一对象时,一条线程的访问还没结束,CPU切换到另一条线程工作,导致数据访问异常。
任何对象都可以。如果要在主函数中创建多个对象,要实现同步可将锁对象加static关键字 |
1、同步代码块
2、同步方法:
public synchronized void print1() { 同步代码 }
public synchronized void print2() { 同步代码 }
// 使用调用当前方法的对象即this作为锁对象。
如果想要同步方法和同步代码块同步,使用this作为锁对象。
三、多线程通信:必须是在同步代码中
使用锁对象的wait( )方法进行等待。在同步方法中锁对象为this,即this.wait( );
使用锁对象的notify( )方法随即唤醒等待的线程。
使用锁对象的notifyAll( )方法唤醒所有等待的进程。
定义标志变量在线程间切换。 int flag = 1;
四、JDK1.5之后的同步与通信
1、同步
(1)导入包:import java.util.concurrent.locks.ReentrantLock;
(2)创建锁对象:ReentrantLock lock = new ReentrantLock( );
(3)上锁:lock.lock( );
(4)解锁:lock.unlock( );
2、通信
(1)导入包:java.util.concurrent.locks.ReentrantLock;
java.util.concurrent.locks.Condition;
(2)创建锁对象:ReentrantLock lock = new ReentrantLock( );
使用锁对象的newCondition()方法获取Condition对象:
Condition c1 =lock.newCondition( );
Condition c2 =lock.newCondition( );
(3)用不同的Condition对象的await( )方法和signal( )方法控制不同线程的等待和唤醒:
c1.await(); //线程在c1对象上等待
c1.signal(); //唤醒在c1对象上等待的线程