一个应用程序我们称为一个进程,一个进程里面可以包含很多线程
其实要高效利用线程,需要把线程都放在线性池中,而不是我们现在这样显性使用线性,线性池还未学到,后续学到再补
线程有安全和不安全的
一、怎么添加线程,获取线程名
1、MyRun.java
Runnable是线程里面的一个类,使用的是接口,所以可以实现
public class MyRun implements Runnable{
@Override
public void run() {
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是" + Thread.currentThread().getName());
}
}
}
2、MyThread.java
继承线程,构造一个空参,可以直接new,构造一个有名字的函数,可以直接给线程一个名字
public class MyThread extends Thread {
public MyThread() { }
public MyThread(String name) {
super(name);
}
@Override
public void run(){
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 获取代码名字
System.out.println("我是" + Thread.currentThread().getName());
}
}
}
3、ThreadTest.java
对之前的写的两个类new,分别赋予名字,在这个while循环里面的得到的线程名字是main,也就是主线程
public class ThreadTest {
public static void main(String[] args) {
Thread t1 = new MyThread("我是一号线程");
// 只有调用start方法才能开启一个新的线程,否则使用run()会一直被while卡住,执行main线程
t1.start();
Thread t2 = new MyThread("我是二号线程");
t2.start();
Thread t3 = new Thread(new MyRun(),"run接口的线程");
t3.start();
while (true){
try {
Thread.sleep(1000);
} catch (InterruptedException e) {
e.printStackTrace();
}
System.out.println("我是" + Thread.currentThread().getName());
}
}
}
二、线程安全与越界
在注释中我有简单写线程数据不足和越界的问题,还简单提及了list安全的线程是什么
1、ThreadTest.java
public class ThreadTest {
// 静态的全都大写
// arraylist不是安全的线程,但是Vector一定是安全的
public static List<Integer> LIST = new Vector<>();
// hashmap不是安全的线程,但Hashtable是安全的
public static Map map = new Hashtable();
public static void main(String[] args) {
for (int i = 0; i < 5; i++) {
Thread t = new Thread(new MyRun());
t.start();
}
try {
Thread.sleep(5000);
} catch (InterruptedException e) {
e.printStackTrace();
}
// 拿到的数据不一定是500,可能400多也可能越界。
// 不足500的原因是因为,当电脑执行速度过快,第一个在处理线程的人还没有处理完,
// 第二个人就开始工作了,那么第二个人拿到的下标很有可能就是第一个人的,那么数据就会不足500
// 这样的线程是不安全的,安全的线程应当时一个线程执行完了再执行另一个
// 越界是因为当工作的人已经拿到最后的一个数据了,此时数据要扩容,temp就会指向新扩容的部分,但工作的人还没有指向新的扩容部分,就查看扩容的部分,就会出现越界
System.out.println("---------list共有" + LIST.size() + "个数据");
}
}
2、MyRun.java
public class MyRun implements Runnable{
@Override
public void run() {
System.out.println("添加了一个数据");
for (int i = 0; i < 100; i++) {
ThreadTest.LIST.add(i);
}
}
}
三、StringBuilder和StringBuffer
一切尽在代码中
public class StringTest {
public static void main(String[] args) {
// StringBuilder、StringBuffer和String有不同之处,StringBuilder可以多次被改写,String无法被改写
// StringBuilder、StringBuffer使用方法一样
// StringBuilder是线程不安全的,但速度快,线程不安全的都比线程安全的快
StringBuilder sb = new StringBuilder();
sb.append("aa").append("bb").append("cc");
System.out.println(sb.toString());
// StringBuffer的线程是安全的,运行速度略慢
StringBuffer sb2 = new StringBuffer();
sb.append("aa").append("xx");
System.out.println(sb2.toString());
}
}
public class ThreadTest {
// 静态的全都大写
// arraylist不是安全的线程,但是Vector一定是安全的
//public static List<Integer> LIST = new Vector<>();
// hashmap不是安全的线程,但Hashtable是安全的
//public static Map map = new Hashtable();
public static StringBuilder SB = new StringBuilder();
public static void main(String[] args) {
List<String> list = new ArrayList<>();
for (int i = 0; i < 1000; i++) {
// UUID是根据你的电脑生成的这个世界上此刻唯一的内容
System.out.println(UUID.randomUUID().toString());
}
StringBuilder sb = new StringBuilder();
for (String s : list) {
sb.append(s).append("_");
}
System.out.println(sb.toString());
}
}