java多线程
java 多线程是在java中常用到的技术, 下面先从一个最简单的线程创建开始讲起。
多线程 的好处:
1. 解决一个进程中可以同时执行多个任务的问题。
2. 提高了资源利用率。
多线程的弊端:
1. 增加了cpu的负担。
2. 降低了一个进程中线程 的执行概率。
3. 出现了线程 安全问题。
4. 会引发死锁现象。
自定义线程 的实现方式:
方式一 :
1. 自定义一个类继承Thread类。
2. 重写Thread类的run方法,把自定义线程的任务代码写在run方法上。
3. 创建Thread的子类对象,并且调用start方法启动一个线程。
注意:千万不要直接调用run方法,调用start方法的时候线程就会开启,线程一旦开启就会执行run方法中代码,如果直接调用run方法,那么就 相当于调用了一个普通的方法而已。
//创建一个类让这个类继承Thread类,这个类就是个线程类了。
public class Demo1 extends Thread {
//重写此类的构造函数,给这个线程起一个名称
public Demo1(String name){
super(name);
}
//重写父类的run方法
public void run() {
//输出从1到100
for(int i=0;i<100;i++){
System.out.println(this.getName()+i);
}
}
public static void main(String[] args) throws Exception{
//实例化线程
Demo1 dome=new Demo1("徐周");
//给当前线程定一个暂定时间,暂定时间结束后线程继续执行
dome.sleep(1000);
//起动线程,从start()开始线程才开始真正等待CPU动行
dome.start();
//输出当前线程的优先级别java线程一共10个级别1-10
System.out.println(dome.getPriority());
//输出主线程的优先级别
System.out.println(Thread.currentThread().getPriority());
for (int i = 0; i < 100; i++) {
System.out.println("dddd主线程");
}
}
}
一个最简单的java多线程就写完了,下面我们再来看线程安全问题。
package com.xuzhou;
public class xuzhou2 extends Thread {
static int sum=50;
static Object o=new Object();
public xuzhou2(String name){
super(name);
}
@Override
public void run() {
while(true){
if(sum>0){
System.out.println(Thread.currentThread().getName()+"出售了第"+sum+"张票");
sum--;
}else{
System.out.println("票已经卖完了");
break;
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
xuzhou2 mode1=new xuzhou2("窗口1");
xuzhou2 mode2=new xuzhou2("窗口2");
xuzhou2 mode3=new xuzhou2("窗口3");
mode1.start();
mode2.start();
mode3.start();
}
}
运行这段代码,我们会发现一个问题,就是同一个数据会出现2次,为什么这样呢?我们已经定义了 static int sum=50 为静态成员了,但运行的时候还是会出现sum相同的数据,这次是线程安全问题,因为CPU会抢资源,3个线程都在操作一个run方法,
当一个线程刚刚输出System.out.println(Thread.currentThread().getName()+"出售了第"+sum+"张票");的时候还没来得急Sum--,这个时候CPU有可能就会抢资源,第二个线程这个时候进来了,所以就会造成输出相同的数,出现线程安全问题。
程安全出现 的根本原因:
1. 存在两个或者两个以上 的线程对象共享同一个资源。
2. 多线程操作共享资源的代码 有多句。
这个问题怎么解决呢,其实很好解决在run方法里面加一个synchronized ("锁")就行,如下:
package com.xuzhou;
public class xuzhou2 extends Thread {
static int sum=50;
static Object o=new Object();
public xuzhou2(String name){
super(name);
}
@Override
public void run() {
while(true){
synchronized ("锁") {
if(sum>0){
System.out.println(Thread.currentThread().getName()+"出售了第"+sum+"张票");
sum--;
}else{
System.out.println("票已经卖完了");
break;
}
}
}
}
/**
* @param args
*/
public static void main(String[] args) {
xuzhou2 mode1=new xuzhou2("窗口1");
xuzhou2 mode2=new xuzhou2("窗口2");
xuzhou2 mode3=new xuzhou2("窗口3");
mode1.start();
mode2.start();
mode3.start();
}
}
运行这段代码,就不会再出现线程安全的问题了,为什么加上synchronized (锁对象)就不会出现线程安全问题呢?
java中每个对象都有一个锁,默认对象是没有加锁的,当我们加上synchronized (锁对象)时,这个对象就会锁住了,当这个对象被锁住时,别的进程就无法访问些对象了,只有当前进程出了这个ynchronized (锁对象)时 ,对象会再次打开,别的进程才能进来,这样就不会出现 线程安全问题了。
同步函数synchronized要注意的事项 :
1. 如果是一个非静态的同步函数的锁 对象是this对象,如果是静态的同步函数的锁 对象是当前函数所属的类的字节码文件(class对象)。
2. 同步函数的锁对象是固定的,不能由你来指定 的。
先写到这,有时间一点一点完善。