线程创建有两种形式:
1:实现runnable接口--在thread构造中创建实现了runnable接口的类--调用start方法
2:从thread类继承并重写run方法(在main函数中就不需要new thread了,直接调用start方法)
【线程创建方法一:继承thread】
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
th.start();
for(int i =0; i<10;i++){
System.out.println("thread1 start");
}
}
}
class Thread1 extends Thread{
public void run(){
for(int i = 0; i< 10;i++){
System.out.println("hello world");
}
}
}
【为什么要覆盖run方法】
该类定义了一个功能,存储要运行代码的,该存储功能就叫做run方法
主线程中存储代码的地方是main方法,其他线程内存储代码的地方是run方法
start方法启动线程并执行run方法
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1("thread");
th.start();
for(int i =0; i<10;i++){
System.out.println("thread1 start");
}
}
}
class Thread1 extends Thread{
Thread1(String name){
super(name);
}
/* String name;
Thread1(String name){不起作用
this.name = name;
}*/
public void run(){
for(int i = 0; i< 10;i++){
System.out.println(Thread.currentThread().getName()+i);
}
}
}
【创建线程第二种方法:实现runnable接口】
package demo;
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
Thread thread1 = new Thread(th);
Thread thread2 = new Thread(th);
Thread thread3 = new Thread(th);
Thread thread4 = new Thread(th);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
class Thread1 implements Runnable{
private int ticket = 100;
public void run(){
while(true){
if(ticket>0)
System.out.println(Thread.currentThread().getName()+"-----"+ticket--);
}
}
}
问题:为什么要将runnable子类对象作为参数传递给Tread构造函数
答:因为自定义run方法实现所属的对象是runnable接口子类对象,所以要启用run方法,就必须明确该run方法所属对象
问题:当一个线程将共享数据没有执行完时,其他线程参与进来,会导致线程安全问题
解决办法:同步代码块 synchronized(对象){需要被同步的代码块}
package demo;
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
Thread thread1 = new Thread(th);
Thread thread2 = new Thread(th);
Thread thread3 = new Thread(th);
Thread thread4 = new Thread(th);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
class Thread1 implements Runnable{
private int sum;
@Override
public void run() {
while(true)
add(10);
}
public synchronized void add(int n){
if(sum<10000){
sum+=n;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"--"+sum);
}
}
}
【函数需要被对象调用,函数都有一个所属对象调用即this,所以同步对象的锁是this】
package demo;
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
Thread thread1 = new Thread(th);
Thread thread2 = new Thread(th);
thread1.start();
thread2.start();
}
}
class Thread1 implements Runnable{
private int sum;
boolean flag = true;
@Override
public void run() {
if(flag)
while(true)
synchronized(this){//如果改为obj不是同一个锁,无法同步
if(sum<1000){
sum+=10;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-code-"+sum);
}
}
else{
add();
}
}
public synchronized void add(){//同步的锁为this
if(sum<1000){
sum+=10;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-add-"+sum);
}
}
}
【静态同步对象锁是class】
如果同步函数被静态修饰后使用的锁不再是this,因为静态方法中不可以定义this
静态进内存时,内存中没有本类对象,但有本类对应的字节码文件对象,即类名.class,该对象的类型是class
package demo;
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
Thread thread1 = new Thread(th);
Thread thread2 = new Thread(th);
thread1.start();
thread2.start();
}
}
class Thread1 implements Runnable{
private static int sum;//不加static在堆内存共享数据,加上在方法区共享数据
boolean flag = true;
@Override
public void run() {
if(flag)
while(true)
synchronized(Thread1.class){
if(sum<1000){
sum+=10;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-code-"+sum);
}
}
else{
add();
}
}
public static synchronized void add(){//同步的锁为this
if(sum<1000){
sum+=10;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-add-"+sum);
}
}
}
【设计模式】
【饿汉式】
class Single{
private static final Single single = new Single();
private Single(){}
public static Single getInstant(){
return single;
}
}
【懒汉式】对象延迟加载
class Single{
private static Single single=null;
private Single(){};
public static Singel getInstant(){
if(single == null){
synchronized(Single.class){
if(single == null){
single = new Single();
}
}
}
else return single;
}
}
【编写一个死锁程序】
package demo;
public class Demo {
public static void main(String[] args) {
Thread th1 = new Thread(new DeadLock(true));
Thread th2 = new Thread(new DeadLock(false));
th1.start();
th2.start();
}
}
class DeadLock implements Runnable{
boolean flag;
public DeadLock(boolean flag){
this.flag = flag;
}
@Override
public void run() {
if(flag){
while(true){
synchronized(Lock.lock1){
System.out.println("下来需要lock2解锁");
synchronized(Lock.lock2){
System.out.println("下来需要lock1解锁");
}
}
}
}else{
while(true){
synchronized(Lock.lock2){
System.out.println("下来需要lock1解锁");
synchronized(Lock.lock1){
System.out.println("下来需要lock2解锁");
}
}
}
}
}
}
class Lock{
static Object lock1 = new Object();
static Object lock2 = new Object();
}
【线程间通讯】
多个线程操作同一个资源,操作动作不同
【等待唤醒】
wait() notify() notifyAll() 都用在同步中,因为要对持有锁的线程操作
为什么这些操作线程的方法要定义在Object中:
因为锁可以使任意对象,任意对象可以调用的方法应定义在Object中
【生产者消费者】
package demo;
public class Demo {
public static void main(String[] args) {
Res res = new Res();
Producer p = new Producer(res);
Consumer c = new Consumer(res);
Thread th1 = new Thread(p);
Thread th2 = new Thread(p);
Thread th3 = new Thread(c);
Thread th4 = new Thread(c);
th1.start();
th2.start();
th3.start();
th4.start();
}
}
class Producer implements Runnable{
private Res res;
Producer(Res res){
this.res = res;
}
@Override
public void run() {
while(true){
res.set("name");
}
}
}
class Consumer implements Runnable{
private Res res;
Consumer(Res res){
this.res = res;
}
@Override
public void run() {
while(true){
res.out();
}
}
}
class Res{
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name){
while(flag){//保证唤醒后执行判断,但会造成全部等待,因此后面应用notifyAll
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
flag = true;
this.notifyAll();
}
public synchronized void out(){
while(!flag)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"...消费者......"+this.name);
flag = false;
this.notifyAll();
}
}
【其他方法】
interrupt() 当没有指定方法让冻结的线程恢复,对冻结的线程进行清除(会出现出现Exception 可以在catch中进行操作结束线程)
join() 请求cpu直至该线程结束
setDaemon() 设置为后台线程
setPriority(Thread.MAX_PRIORITY)
yield() 临时释放执行权
1:实现runnable接口--在thread构造中创建实现了runnable接口的类--调用start方法
2:从thread类继承并重写run方法(在main函数中就不需要new thread了,直接调用start方法)
【线程创建方法一:继承thread】
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
th.start();
for(int i =0; i<10;i++){
System.out.println("thread1 start");
}
}
}
class Thread1 extends Thread{
public void run(){
for(int i = 0; i< 10;i++){
System.out.println("hello world");
}
}
}
【为什么要覆盖run方法】
该类定义了一个功能,存储要运行代码的,该存储功能就叫做run方法
主线程中存储代码的地方是main方法,其他线程内存储代码的地方是run方法
start方法启动线程并执行run方法
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1("thread");
th.start();
for(int i =0; i<10;i++){
System.out.println("thread1 start");
}
}
}
class Thread1 extends Thread{
Thread1(String name){
super(name);
}
/* String name;
Thread1(String name){不起作用
this.name = name;
}*/
public void run(){
for(int i = 0; i< 10;i++){
System.out.println(Thread.currentThread().getName()+i);
}
}
}
【创建线程第二种方法:实现runnable接口】
package demo;
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
Thread thread1 = new Thread(th);
Thread thread2 = new Thread(th);
Thread thread3 = new Thread(th);
Thread thread4 = new Thread(th);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
class Thread1 implements Runnable{
private int ticket = 100;
public void run(){
while(true){
if(ticket>0)
System.out.println(Thread.currentThread().getName()+"-----"+ticket--);
}
}
}
问题:为什么要将runnable子类对象作为参数传递给Tread构造函数
答:因为自定义run方法实现所属的对象是runnable接口子类对象,所以要启用run方法,就必须明确该run方法所属对象
问题:当一个线程将共享数据没有执行完时,其他线程参与进来,会导致线程安全问题
解决办法:同步代码块 synchronized(对象){需要被同步的代码块}
package demo;
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
Thread thread1 = new Thread(th);
Thread thread2 = new Thread(th);
Thread thread3 = new Thread(th);
Thread thread4 = new Thread(th);
thread1.start();
thread2.start();
thread3.start();
thread4.start();
}
}
class Thread1 implements Runnable{
private int sum;
@Override
public void run() {
while(true)
add(10);
}
public synchronized void add(int n){
if(sum<10000){
sum+=n;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"--"+sum);
}
}
}
【函数需要被对象调用,函数都有一个所属对象调用即this,所以同步对象的锁是this】
package demo;
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
Thread thread1 = new Thread(th);
Thread thread2 = new Thread(th);
thread1.start();
thread2.start();
}
}
class Thread1 implements Runnable{
private int sum;
boolean flag = true;
@Override
public void run() {
if(flag)
while(true)
synchronized(this){//如果改为obj不是同一个锁,无法同步
if(sum<1000){
sum+=10;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-code-"+sum);
}
}
else{
add();
}
}
public synchronized void add(){//同步的锁为this
if(sum<1000){
sum+=10;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-add-"+sum);
}
}
}
【静态同步对象锁是class】
如果同步函数被静态修饰后使用的锁不再是this,因为静态方法中不可以定义this
静态进内存时,内存中没有本类对象,但有本类对应的字节码文件对象,即类名.class,该对象的类型是class
package demo;
public class Demo {
public static void main(String[] args) {
Thread1 th = new Thread1();
Thread thread1 = new Thread(th);
Thread thread2 = new Thread(th);
thread1.start();
thread2.start();
}
}
class Thread1 implements Runnable{
private static int sum;//不加static在堆内存共享数据,加上在方法区共享数据
boolean flag = true;
@Override
public void run() {
if(flag)
while(true)
synchronized(Thread1.class){
if(sum<1000){
sum+=10;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-code-"+sum);
}
}
else{
add();
}
}
public static synchronized void add(){//同步的锁为this
if(sum<1000){
sum+=10;
try{Thread.sleep(10);}catch(Exception e){}
System.out.println(Thread.currentThread().getName()+"-add-"+sum);
}
}
}
【设计模式】
【饿汉式】
class Single{
private static final Single single = new Single();
private Single(){}
public static Single getInstant(){
return single;
}
}
【懒汉式】对象延迟加载
class Single{
private static Single single=null;
private Single(){};
public static Singel getInstant(){
if(single == null){
synchronized(Single.class){
if(single == null){
single = new Single();
}
}
}
else return single;
}
}
【编写一个死锁程序】
package demo;
public class Demo {
public static void main(String[] args) {
Thread th1 = new Thread(new DeadLock(true));
Thread th2 = new Thread(new DeadLock(false));
th1.start();
th2.start();
}
}
class DeadLock implements Runnable{
boolean flag;
public DeadLock(boolean flag){
this.flag = flag;
}
@Override
public void run() {
if(flag){
while(true){
synchronized(Lock.lock1){
System.out.println("下来需要lock2解锁");
synchronized(Lock.lock2){
System.out.println("下来需要lock1解锁");
}
}
}
}else{
while(true){
synchronized(Lock.lock2){
System.out.println("下来需要lock1解锁");
synchronized(Lock.lock1){
System.out.println("下来需要lock2解锁");
}
}
}
}
}
}
class Lock{
static Object lock1 = new Object();
static Object lock2 = new Object();
}
【线程间通讯】
多个线程操作同一个资源,操作动作不同
【等待唤醒】
wait() notify() notifyAll() 都用在同步中,因为要对持有锁的线程操作
为什么这些操作线程的方法要定义在Object中:
因为锁可以使任意对象,任意对象可以调用的方法应定义在Object中
【生产者消费者】
package demo;
public class Demo {
public static void main(String[] args) {
Res res = new Res();
Producer p = new Producer(res);
Consumer c = new Consumer(res);
Thread th1 = new Thread(p);
Thread th2 = new Thread(p);
Thread th3 = new Thread(c);
Thread th4 = new Thread(c);
th1.start();
th2.start();
th3.start();
th4.start();
}
}
class Producer implements Runnable{
private Res res;
Producer(Res res){
this.res = res;
}
@Override
public void run() {
while(true){
res.set("name");
}
}
}
class Consumer implements Runnable{
private Res res;
Consumer(Res res){
this.res = res;
}
@Override
public void run() {
while(true){
res.out();
}
}
}
class Res{
private String name;
private int count = 1;
private boolean flag = false;
public synchronized void set(String name){
while(flag){//保证唤醒后执行判断,但会造成全部等待,因此后面应用notifyAll
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
}
this.name = name+"--"+count++;
System.out.println(Thread.currentThread().getName()+"...生产者..."+this.name);
flag = true;
this.notifyAll();
}
public synchronized void out(){
while(!flag)
try {
wait();
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println(Thread.currentThread().getName()+"...消费者......"+this.name);
flag = false;
this.notifyAll();
}
}
【其他方法】
interrupt() 当没有指定方法让冻结的线程恢复,对冻结的线程进行清除(会出现出现Exception 可以在catch中进行操作结束线程)
join() 请求cpu直至该线程结束
setDaemon() 设置为后台线程
setPriority(Thread.MAX_PRIORITY)
yield() 临时释放执行权