Java学习之线程

来源:互联网 发布:淘宝网店服装模特招聘 编辑:程序博客网 时间:2024/05/21 14:47

一、线程和进程

1、线程是依赖进程存在的

进程:正在运行的程序

线程:进程的执行路径,执行单元

二、多线程的两种方式

1、继承Thread类

2、实现Runnable接口

package com.edu_01;public class Test {public static void main(String[] args) {//继承Thread类,这个子类中重写了run()方法//当我们创建了线程对象并且启动了他的实例的时候,我们就相当于开启了一个线程//MyThread mt = new MyThread();//MyThread mt2 = new MyThread();////可以直接开启线程,这个包括两部分,1.开启了这个线程 2.调用了这个线程中的run()方法//mt.start();//mt2.start();//实现runable接口重写run()方法MyRunable mr = new MyRunable();//实现runable接口没法直接调用start方法开启线程,//必须再利用thread的有参构造方法:public Thread(Runnable target)才能开启线程Thread td = new Thread(mr);Thread td2 = new Thread(mr);//开启线程//不同的线程可以同时开始//但是相同的线程只能开启一个td.start();//td.start();//java.lang.IllegalThreadStateExceptiontd2.start();}}

三、线程方法

1、开启线程 start(),这个会有两步,一是开启线程,二是执行run()方法里面的代码

注意:之所以要重写run()是应为每个线程要执行的代码是不一样的,所以我们需要将每个线程自己独立执行的代码写到run()里面去

不同的线程可以同时启动,同一个线程不能启动多次

2、线程休眠 Thread.sleep(毫秒值)

3、线程名称 setName(),getName()

4、线程优先级setPriority(默认值是5,区间在1-10之间)实际上就是设置你抢占cpu执行权的概率

package com.edu_02;public class MyThread extends Thread{@Overridepublic void run() {for (int i = 0; i < 100; i++) {try {Thread.sleep(100);//设置休眠时间} catch (InterruptedException e) {// TODO Auto-generated catch blocke.printStackTrace();}System.out.println(this.getName()+i);//获取线程的名字}}}
package com.edu_02;public class Test {public static void main(String[] args) {//创建线程实例MyThread mt = new MyThread();MyThread mt2 = new MyThread();MyThread mt3 = new MyThread();//给线程设置名字mt.setName("狐狸");mt2.setName("老虎");mt3.setName("狮子");//设置线程优先级,线程的调度及优先级setPriority(10)(注意默认值是5,区间在1-10之间)//注意是提高线程的优先级,但是这是一个概率问题,并无法保证一定可以把线程调到前面mt.setPriority(10);//开启线程mt.start();mt2.start();mt3.start();}}

四、线程安全

判断是否存在线程安全有以下三点

1、是否是多线程

2、是否有共享数据

3、是否有多条语句操作共享数据

五、如何解决线程安全

如果线程安全的话会降低执行效率

方法一、同步代码块

synchronized(对象){

需要被同步的代码

}

注意:要想保证线程安全,必须要保证使用同一把锁(对象),如果使用不同的锁是不能保证线程安全的,其中锁(对象)是任意对象,需要被同步的代码是被线程执行的代码

方式二、同步方法(仅适用于实现runnable接口)

public synchronized void 方法名(){

同步代码

}

静态同步方法:

类的字节码对象

public static synchronized void 方法名() {

需要同步的代码

}

六、匿名内部类使用多线程

方式一:

new Thread(){

public void run(){

...

}

}.start();

方式二:

new Thread(new Runnable){

public void run(){

...

}

}.start();

public class Test {public static void main(String[] args) {//创建线程对象new Thread(){public void run() {for (int i = 0; i < 10; i++) {System.out.println("a"+i);}};}.start();new Thread(new Runnable() {@Overridepublic void run() {for (int i = 0; i < 10; i++) {System.out.println("b"+i);}}}).start();}}
使用匿名内部类解决单例模式中懒汉模式的线程安全问题:

package com.edu_09;/** * 利用匿名内部类,启动多个线程,验证单例设计模式之懒汉式所存在的缺陷,      当使用多线程来搞的时候就不单例了。。 * */public class SingleDemo {private SingleDemo() {}private static SingleDemo single = null;//如果加上休眠时间,再利用匿名内部类创建多线程的话,会存在线程安全问题,这是只要往这个公共方法上添加synchronized关键字,就可以解决public synchronized static SingleDemo getSilgle(){try {Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}if (single==null) {single = new SingleDemo();}else{}return single;}}

七、JDK5的Lock锁,前面所有的锁都没法手动释放

static Lock lock = new ReentrantLock();

加锁:lock.lock();

释放锁:lock.unlock();

好处:可以让我们明确的知道哪里加锁和释放锁

import java.util.concurrent.locks.Lock;import java.util.concurrent.locks.ReentrantLock;public class ShellTicket implements Runnable{static int tickets = 100;static Lock lock = new ReentrantLock();@Overridepublic void run() {//让窗口一直处于打开的状态while (true) {try {//加锁lock.lock();if (tickets>0) {try {//在加入休眠之后出现了重复票和0张-1张票,出现了线程安全问题Thread.sleep(100);} catch (InterruptedException e) {e.printStackTrace();}System.out.println(Thread.currentThread().getName()+"正在出售第"+tickets--+"票");}} finally{//finally里面的代码一定会执行//释放锁lock.unlock();}}}}

八、死锁问题

由于同步嵌套造成的,锁里面嵌套一个锁,出现同步嵌套

九、线程等待和唤醒

线程等待:锁对象调用wait()

线程唤醒:锁对象调用notify()

注意:线程等待的时候是会释放锁的,但是sleep在执行过程中是不会释放锁的



原创粉丝点击