首页 文章 精选 留言 我的

精选列表

搜索[镜像无法拉取],共10000篇文章
优秀的个人博客,低调大师

踏破铁鞋无觅处,从AsyncTask学Android线程池

android对于主线程的响应时间限制的非常严格,稍有不慎就会遇到Application Not Responding(ANR)的弹框。用户可以轻点手指关掉你的APP。官方文档写的非常明确!同时,保持应用随时响应用户的操作也是良好用户体验的前提。 线程的开始和结束 要做到以上多线程是必不可少的。课本会告诉你什么时候开辟一个线程,但是很少说的一个很重要的问题是结束。比如,我现在在Activity里有一个工作需要创建一个线程执行,但是这个Activity在进入后台后不幸遇到系统回收资源被销毁了。但是这个线程还在漫无目的的游走,耗费资源。 如何结束?先创建一个: mThread = Thread(Runnable { // do something here... }) mThread?.start() 以上使用kotlin的lambda表达式简写了创建Runnable对象部分的代码。主旨还是创建了一个Runnable对象,并将其作为参数传入Thread。 如何让一个Thread能够退出呢?这就要在Runnable身上下功夫了。首先添加一个是否停止的标识isCancelled,一旦值为true则停止线程的运行,否则继续。我们这里不讨论Thread#interrupt()这个方法,这个方法诡异的地方太多。 首先要给Runnable“添加一个属性”作为上文的是否停止的标识。直接添加时不可能的,Runnable只是一个interface,不是class。所以要实现这个借口为一个抽象类,这样就可以添加属性了。 abstract class CancelableRunnable() : Runnable { var isCancelled: Boolean = false } 这里使用抽象类,是因为run()方法的实现留给使用的时候给出。 var runnable = object : CancelableRunnable() { override fun run() { if (isCancelled) { var msg = mHandler.obtainMessage(THREAD_CANCELLED) mHandler.sendMessage(msg) return } Thread.sleep(2000) if (isCancelled) { var msg = mHandler.obtainMessage(THREAD_CANCELLED) mHandler.sendMessage(msg) return } var msg = mHandler.obtainMessage(THREAD_FINISHED) mHandler.sendMessage(msg) } } Thread.sleep(2000)用来模拟一个费时的任务。开始之前检测是否取消了线程的执行,执行之后在检测。之后的检测是有的时候任务执行之后需要有持久化处理结果或者修改任务完成情况的标识之类的动作,如果已经取消了线程的执行,即使任务执行完成也不持久化结果、不修改完成情况。 最后都检测完成之后如果没有取消线程,则发出任务完成执行的消息。 发出和处理这些消息的Handler的定义: var mHandler = object : Handler() { override fun handleMessage(msg: Message?) { when (msg?.what) { THREAD_CANCELLED -> { mResultTextView.text = "thread cancelled" } THREAD_FINISHED -> { mResultTextView.text = "thread finished" } else -> { mResultTextView.text = "what's going on" } } } } 运行在UI线程的Handler检测从线程发出的消息,如果是THREAD_CANCELLED那就是线程已经取消了,如果是THREAD_FINISHED那就是线程完全运行结束。之后根据message的消息设置TextView的文本内容。 这里使用了两个按钮来启动和停止线程: findViewById(R.id.start_button)?.setOnClickListener { v -> runnable.isCancelled = false mThread = Thread(runnable) mThread?.start() mResultTextView.text = "Thread running..." } findViewById(R.id.stop_button)?.setOnClickListener { v -> this.runnable.isCancelled = true } 上面用到的Runnable是只做一件事的,如果是连续不断的循环很多事的话也可以使用white语句来控制是否一直执行线程的工作。一旦设置为停止线程,则停止线程任务的循环跳出Runnable#run()方法,结束线程。 完整代码放在附录中。 所以,如果你在Activity里开辟了一个线程,在Activity被回收的时候结束线程就可以这么做: override fun onDestroy() { super.onDestroy() this.runnable.isCancelled = true } 这样就再也不用担心Activity挂了,线程还阴魂不散了。 AsyncTask 既然缘起AsyncTask那就肯定需要读者一起了解一下相关的概念。 比起来使用Handler+Thread+Runnable的多线程异步执行模式来说,使用AsyncTask是简单了非常的多的。 先简单了解一下AsyncTask。 public abstract class AsyncTask<Params, Progress, Result> AsyncTask是一个抽象泛型类。三个类型Params,Progress,Result分别对应的是输入参数的类型,精度更新使用的类型,最后是返回结果的类型。其中任何一个类型如果你不需要的话,可以使用java.lang.Void代替。 继承AsyncTask给出自己的实现,最少需要实现doInBackground方法。doInBackground方法是在后台线程中运行的。如果要在任务执行之后更新UI线程的话还至少需要给出onPostExecute方法的实现,在这个方法中才可以更新UI。 上述的两个方法已经构成了一个AsyncTask使用的基本单元。在后台线程处理一些任务,并在处理完成之后更新UI。但是如果一个任务比较长,只是在最后更新UI是不够的,还需要不断的提示用户已经完成的进度是多少。这就是需要另外实现onProgressUpdate方法。并在doInBackground方法中调用publishProgress方法发出每个任务的处理进度。 这个AsyncTask总体上就是这样的了: inner class DemoAsyncTask() : AsyncTask<String, Int, String>() { // var isRunning = true override fun doInBackground(vararg params: String?): String? { Log.i(TAG, "##AsyncTask doing something...") var i = 0 val TOTAL = 100000000 var progress = 0 while (i < TOTAL) { Log.d(TAG, "doning jobs $i is cancelled $isCancelled") i++ var currentProgress = i.toFloat() / TOTAL if (currentProgress > progress && Math.abs(currentProgress - progress) > 0.1) { progress = currentProgress publishProgress((progress * 100).toInt()) } } } Log.d(TAG, "doing jobs $i is cancelled $isCancelled") return "Task done" } override fun onPostExecute(result: String?) { this@CancalableActivity.mAsyncTextView?.text = result } override fun onProgressUpdate(vararg values: Int?) { mAsyncTextView?.text = "${mAsyncTextView?.text ?: "Async task..."} progress: ${values?.get(0) ?: 0}" } } 到这里各位读者应该对AsyncTask已经有一个总体的认识了。后台任务在doInBackground处理,处理过程的百分比使用publishProgress方法通知,并在onProgressUpdate方法中更新UI的百分比。最后任务处理全部完成之后在onPostExecute更新UI,显示全部完成。 怎么取消一个任务的执行呢?这个机本身还上面的线程的取消基本上一样。只是AsyncTask已经提供了足够的属性和方法完成取消的工作。直接调用AsyncTask#cancel方法就可以发出取消的信号,但是是否可以取消还要看这个方法的返回值是什么。如果是true那就是可以,否则任务不可取消(但是不可取消的原因很可能是任务已经执行完了)。 调用cancel方法发出取消信号,并且可以取消的时候。isCancelled()就会返回true。同时onPostExecute这个方法就不会再被调用了。而是onCancelled(object)方法被调用。同样是在doInBackground这个方法执行完之后调用。所以,如果想要在取消任务执行后尽快的调用到onCancelled(object)的话,就需要在onInBackground的时候不断的检查isCancelled()是否返回true。如果返回的是true就跳出方法的执行。 inner class DemoAsyncTask() : AsyncTask<String, Int, String>() { // var isRunning = true override fun doInBackground(vararg params: String?): String? { Log.i(TAG, "##AsyncTask doing something...") var i = 0 val TOTAL = 1000000 var progress = 0.0f while (i < TOTAL && !isCancelled) { Log.d(TAG, "doning jobs $i is cancelled $isCancelled") i++ var currentProgress = i.toFloat() / TOTAL if (currentProgress > progress && Math.abs(currentProgress - progress) > 0.1) { progress = currentProgress publishProgress((progress * 100).toInt()) } } Log.d(TAG, "doning jobs $i is cancelled $isCancelled") return "Task done" } override fun onPostExecute(result: String?) { this@CancalableActivity.mAsyncTextView?.text = result } override fun onProgressUpdate(vararg values: Int?) { mAsyncTextView?.text = "${mAsyncTextView?.text ?: "Async task..."} progress: ${values?.get(0) ?: 0}" } override fun onCancelled() { Log.i(TAG, "##Task cancelled") // isRunning = false this@CancalableActivity.mAsyncTextView?.text = "###Task cancelled" } // override fun onCancelled(result: String?) { // Log.i(TAG, "##Task cancelled") //// isRunning = false // this@CancalableActivity.mAsyncTextView?.text = result ?: "Task cancelled" // } } onCancelled()是API level 3的时候加入的。onCancelled(Result result)是API level 11的时候加入的。这个在兼容低版本的时候需要注意。 但是一点需要格外注意: AsyncTask一定要在UI线程初始化。不过在**JELLY_BEAN**以后这个问题也解决了。 总之,在UI线程初始化你的`AsyncTask`肯定是不会错的。 线程池 下面就来看看线程池的概念。顾名思义,线程池就是放线程的池子。把费时费力,或者影响响应用户操作的代码放在另外一个线程执行时常有的事。但是如果无顾忌的开辟线程,却会适得其反,严重的浪费系统资源。于是就有了线程池。线程池就是通过某些机制让线程不要创建那么多,能复用就复用,实在不行就让任务排队等一等。 这个机制在线程池的构造函数里体现的非常明显: public ThreadPoolExecutor(int corePoolSize, int maximumPoolSize, long keepAliveTime, TimeUnit unit, BlockingQueue<Runnable> workQueue, ThreadFactory threadFactory, RejectedExecutionHandler handler) corePoolSize线程池里闲着也不回收的线程数量。除非allowCoreThreadTimeOut指定可以回收。 ** maximumPoolSize** 线程池允许的最大线程数。 ** keepAliveTime** 非核心线程(就是如果核心线程数量corePoolSize定义为1的话,第二个就是非核心线程)的超时时间。 unitkeepAliveTime的时间单位,毫秒,秒等。 ** workQueue** 存放execute(Runnable cmd)方法提交的Runnable任务。 ** threadFactory**线程池用来创建新线程用的一个工厂类。 ** handler**线程池达到最大线程数,并且任务队列也已经满的时候会拒绝execute(Runnable cmd)方法提交任务。这个时候调用这个handler。 知道以上基本内容以后,就可以探讨线程池管理线程的机制了。概括起来有三点: 如果线程池的线程数量少于corePoolSize的时候,线程池会使用threadFactory这个线程工厂创建新的线程执行Runnable任务。 如果线程池的线程数量大于corePoolSize的时候,线程池会把Runnable任务存放在队列workQueue中。 线程池的线程数量大于corePoolSize,队列workQueue已满,而且小于maximumPoolSize的时候,线程池会创建新的线程执行Runnable任务。否则,任务被拒。 现在回到AsyncTask。被人广为诟病的AsyncTask是他的任务都是顺序执行的。一个AsyncTask的实例只能处理一个任务。但是在AsyncTask后面处理任务的是一个静态的线程池。在看这个线程池SerialExecutor的execute方法实现: final ArrayDeque<Runnable> mTasks = new ArrayDeque<Runnable>(); public synchronized void execute(final Runnable r) { mTasks.offer(new Runnable() { public void run() { try { r.run(); } finally { scheduleNext(); } } }); if (mActive == null) { scheduleNext(); } } protected synchronized void scheduleNext() { if ((mActive = mTasks.poll()) != null) { // 执行一个task } } 这个线程池SerialExecutor在处理Runnable的传入参数的时候对这个任务进行了重新包装成了一个新的Runnable对象,并且将这个新的对象存入了一个叫做mTasks的队列。这个新的Runnable对象首先执行传入的任务,之后不管有无异常调用scheduleNext方法执行下一个。于是整体的就生成了一个传入的任务都顺序执行的逻辑。 这个线性执行的静态线程池SerialExecutor的实现非常简单。并不涉及到我们前文所说的那么多复杂的内容。在实现上,这个线程池只实现了线程池的最顶层接口Executor。这个接口只有一个方法就是execute(Runnable r)。另外需要强调一点:mTasks的类型ArrayDeque<T>是一个不受大小限制的队列。可以存放任意多的任务。在线程池的讨论中遇到队列就需要看看容量概念。 SerialExecutor只是进行了简单的队列排列。但是在scheduleNext方法的实现上又会用到一个复杂一些的线程池来执行任务的具体执行。这线程池叫做THREAD_POOL_EXECUTOR。我们来具体看看其实现: private static final int CPU_COUNT = Runtime.getRuntime().availableProcessors(); private static final int CORE_POOL_SIZE = CPU_COUNT + 1; private static final int MAXIMUM_POOL_SIZE = CPU_COUNT * 2 + 1; private static final int KEEP_ALIVE = 1; public static final Executor THREAD_POOL_EXECUTOR = new ThreadPoolExecutor(CORE_POOL_SIZE, MAXIMUM_POOL_SIZE, KEEP_ALIVE, TimeUnit.SECONDS, sPoolWorkQueue, sThreadFactory); 这个线程池的实现非常具有现实价值。虽然稍后介绍的系统提供的几种线程池的实现就够用。但是难免遇到一些需要自定义线程池的情况。详细解析如下: CORE_POOL_SIZE线程池的核心线程数量为设备核心数加一。 ** MAXIMUM_POOL_SIZE** 线程池的最大线程数量为核心数的两倍加一。 ** KEEP_ALIVE** 线程池中非核心线程的超时时间为一秒。 ** sPoolWorkQueue ** 线程池存放任务的队列。最大个数为128个。参考上面说的线程池处理机制,会出现任务被拒的情况。排队的线程池SerialExecutor存放任务的队列是可以认为无限长的,但是THREAD_POOL_EXECUTOR的队列最多存放128个任务,加上线程池核心线程的数量,能处理的任务相对有限。出现任务被拒的情况的几率比较大。所以,往AsyncTask里直接添加Runnable对象的时候需要三思。 ** sThreadFactory** 线程池用来创建线程的工厂对象。ThreadFactory是一个只有一个方法Thread newThread(Runnable r);的接口。这里在实现的时候给新创建的线程添加了一个原子计数,并把这个计数作为线程名称传递给了线程的构造函数。 到这里,我们就已经很清楚AsyncTask是如何用一个极其简单的线程池SerialExecutor给任务排队的。又是如何使用一个复杂一些的线程池THREAD_POOL_EXECUTOR来处理具体的任务执行的。尤其是线程池THREAD_POOL_EXECUTOR,在我们实际应用一个自定义的线程池的时候在设定线程池核心线程数量,线程池最大线程数量的时候都依据什么?明显就是设备的CPU核心数。线程分别在不同个CPU核心中做并行的处理。核心数多可以同时处理的线程数就相对较多,相反则会比较少一些。如此设置核心线程数量就会平衡并行处理的任务数量和在处理的过程中耗费的系统资源。 为了让开发者省时省力,系统默认的提供了四种可以适应不同应用条件的线程池: public class Executors { public static ExecutorService newFixedThreadPool(int nThreads) { return new ThreadPoolExecutor(nThreads, nThreads, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>()); } public static ExecutorService newSingleThreadExecutor() { return new FinalizableDelegatedExecutorService (new ThreadPoolExecutor(1, 1, 0L, TimeUnit.MILLISECONDS, new LinkedBlockingQueue<Runnable>())); } public static ExecutorService newCachedThreadPool() { return new ThreadPoolExecutor(0, Integer.MAX_VALUE, 60L, TimeUnit.SECONDS, new SynchronousQueue<Runnable>()); } public static ScheduledExecutorService newScheduledThreadPool(int corePoolSize) { return new ScheduledThreadPoolExecutor(corePoolSize); } } ** newFixedThreadPool** 顾名思义,线程数量固定的线程池,且其数量等于参数指定值。这一类型的线程池的核心线程数量和最大线程数量是一样的。存放任务的队列的容量可以被认为无限大。一旦线程池创建的线程数量等* nThreads*参数值的时候,新增的任务将会被存放在任务队列中等待核心线程可用的时候执行。 ** newSingleThreadExecutor**newFixedThreadPool的一个特殊情况,当mThreads值为1的时候。 ** newCachedThreadPool** 这一类型的线程池中创建的线程都有60秒的超时时间,由于超时时间比较长等于是线程空闲了以后被缓存了60秒。由于核心线程数量为0,所以创建的线程都是非核心线程。也因此超时时间才管用。任务队列SynchronousQueue非常特殊,简单理解就是一个任务都存放不了。而线程池的最大线程数量又设定为Integer.MAX_VALUE,可以认为是无限大。根据线程池处理任务的机制,可以认为有新任务过来就会创建一个线程去处理这个任务,但是如果存在空闲没有超时的线程会优先使用。 ** newScheduledThreadPool** 生成一个ScheduledThreadPoolExecutor实例。可以通过其提供的接口方法设定延迟一定的时间执行或者隔一定的时间周期执行。 来一个例子: import static java.util.concurrent.TimeUnit.*; class BeeperControl { private final ScheduledExecutorService scheduler = Executors.newScheduledThreadPool(1); public void beepForAnHour() { final Runnable beeper = new Runnable() { public void run() { System.out.println("beep"); }; final ScheduledFuture beeperHandle = scheduler.scheduleAtFixedRate(beeper, 10, 10, SECONDS); scheduler.schedule(new Runnable() { public void run() { beeperHandle.cancel(true); } }, 60 * 60, SECONDS); } }} 附录 这里是上面例子中使用的全部代码。 线程的停止: package demo.retrofit2rxjavademo.Activities import android.os.Bundle import android.os.Handler import android.os.Message import android.support.v7.app.AppCompatActivity import android.widget.TextView import demo.retrofit2rxjavademo.R class CancalableActivity : AppCompatActivity() { lateinit var mResultTextView: TextView var mHandler = object : Handler() { override fun handleMessage(msg: Message?) { when (msg?.what) { THREAD_CANCELLED -> { mResultTextView.text = "thread cancelled" } THREAD_FINISHED -> { mResultTextView.text = "thread finished" } else -> { mResultTextView.text = "what's going on" } } } } var mThread: Thread? = null var runnable = object : CancelableRunnable() { override fun run() { if (isCancelled) { var msg = mHandler.obtainMessage(THREAD_CANCELLED) mHandler.sendMessage(msg) return } Thread.sleep(2000) if (isCancelled) { var msg = mHandler.obtainMessage(THREAD_CANCELLED) mHandler.sendMessage(msg) return } var msg = mHandler.obtainMessage(THREAD_FINISHED) mHandler.sendMessage(msg) } } override fun onCreate(savedInstanceState: Bundle?) { super.onCreate(savedInstanceState) setContentView(R.layout.activity_cancalable) mResultTextView = findViewById(R.id.run_result_text_view) as TextView findViewById(R.id.start_button)?.setOnClickListener { v -> runnable.isCancelled = false mThread = Thread(runnable) mThread?.start() mResultTextView.text = "Thread running..." } findViewById(R.id.stop_button)?.setOnClickListener { v -> this.runnable.isCancelled = true } } abstract class CancelableRunnable() : Runnable { var isCancelled: Boolean = false } companion object { val THREAD_FINISHED = 0 val THREAD_CANCELLED = 1 } } 欢迎加群互相学习,共同进步。QQ群:iOS: 58099570 | Android: 572064792 | Nodejs:329118122 做人要厚道,转载请注明出处! 本文转自张昺华-sky博客园博客,原文链接:http://www.cnblogs.com/sunshine-anycall/p/5506154.html ,如需转载请自行联系原作者

优秀的个人博客,低调大师

中国装备制造业寻找新路径:不数字化无未来

经济学家、中国社科院学部委员吕政前不久总结,从1949到远期2049年上下一百年的时间维度来看,中国制造业的发展可以用简单的12个字来概括“从无到有,从少到多,从大到强”,中国毫无疑问的成了世界工厂。 但同时,吕政教授也认为现在的中国制造也正面临很大的麻烦。造成问题的原因有很多,但核心的有这样几个。首先是固定资产投资增速和5年前相比下降了两位数。其次是中国大规模的基础设施建设已经逐渐减少。一直占中国经济增长大头的房地产开发也已经从之前20%增长降到5%左右。市场需求变了,制造业的景气也结束了。更何况,人口红利消失带来的成本上升,也让人力成本占比极高的制造业举步维艰。 在众多制造业细分行业,装备制造业又是受伤害最大的一个行业。因为无论是基础建设,还是房地产,用到最多的制造业产品,除了水泥沙子等大宗原材料,剩下最重要的就是装备制造业这些施工设备。其实即使宏观环境没有变化,制造业可能也面临转型升级的问题。欧美等发达国家的制造业已经更早遇到了需求不足和成本过高的问题。相比较而言,中国市场的宏观环境已经不能算差。涉及多区域运营的跨国公司在这方面有更切身的体会,英特尔中国区总经理夏乐蓓在2015年9月18日第九届政企信息化策略研讨会上就表示,中国在任何行业的发展速度都很快,尤其是制造业,在全球来看都属于增长速度最快的国家行列。 装备制造业数字化云是第一步 正因为有了这样的发展空间。在有挑战的地方,就存在机会。高额固定资产投入带来的快钱不好赚了,中国制造业到了苦练内功的时候,尤其装备制造业是其中最大的门类,也是中国制造2025最重要的门类,所以装备制造业的问题可以上升为整个制造业的问题。 这一切对于工作在装备制造领域十余年的“青岛冷箱”数字化IT项目经理耿峰来说有着最直观的认识,在他看来中国传统装备制造业本身就面临产品创新不足和内部有待优化两大问题。而这些问题可能之前因高增长被掩盖了。要解决这些问题,他的观点是:“产品创新需要利用先进制造技术(IT技术、自动化、机器人等)提升工艺(提高产品吸引力);内部优化则要使用精益制造的模式,从各个环节杜绝浪费。” 而要实现这两种转变,装备制造业马上要面临的问题就是提高对新兴技术的运用。换言之,就是利用IT,将传统工厂升级为数字化工厂。数字化工厂的建设已经成为装备制造业现阶段最重要的任务,但搭建数字化工厂并不是一蹴而就的,首先就要让IT环境适应从研发,到制造,再到后期运维,甚至产品(智能化产品)带来的弹性业务,高密度计算和全程数据可视化。 装备制造业在信息化的建设上走的都相对较早,有比较完整的基础。基础网络、PDM、HR、CRM、ERP等平台基本都建设完成。而当下马上要做的就是云计算上的部署。在英特尔全球数据中心企业应用总监Patrick Buddenbaum看来,企业的业务在发生变化时,云计算非常值得去应用,因为这样企业就有了非常灵敏的业务支持环境。 正因为如此,基于英特尔X86服务器实现虚拟化在装备制造业当中正变得非常主流,同时再部署云计算时也更加得心应手。正是因为有了标准化的工业标准架构,可以很好的降低TCO,同时在业务基于云后,可以明显缩短企业内部的业务部署时间,在工厂每一个环节都可能提出IT需求的时候,都能提高响应速度,提高制造业内部IT部门的服务水平。 由于之前所讲到的,装备制造业的IT建设较早,所以企业内部往往已经有了成熟的IT架构。所以转型云端,到底该怎么做,装备制造企业也说法不一。英特尔对于云计算的策略是“Cloud for All”,即云可以适用于所有类型的应用以及企业,这里就包括混合云的情况。这样的技术即满足了企业长期发展,又保护了企业的现有投资。 耿峰同时认为,云计算的好处还不限于此,“云计算可以把企业的能力和人才都解放出来,让他们去了解业务、钻研业务,站在业务的角度上回归信息化。”因为私有云可以实现起码四大效益:第一,大幅减少IT基础设施的成本和运营成本;第二,使IT基础设施更加稳定、可靠;第三,让IT运营更加灵活高效;第四,节能减排。 当然有了云的支持,还需要有端的配合。尤其在装备制造业中,生产过程是否透明是重中之重,这关乎着企业命脉,也是同其他的制造业最大的不同。装备制造企业的产线工人往往通过操作机器的看板或在监察室了解生产过程,因为设备不具备移动性,这也就要求一人一岗才能知道整个工厂的实时运行环境,第一时间发现问题。而有了移动终端接入云平台,可以很好的提高工厂效率。比如工人在报工上,可以更好的记录、统计和分析员工在项目及非项目上的各项工作任务内容和所花费的时间,考核员工绩效,核算项目人工成本。另外在物料呼叫或物料不良上通过终端可以及时反馈并处理。从管理者到调度班长都可以通过终端实时掌控整个生产过程。 现在基于标准架构的平板电脑,正成为诸多制造业的车间标配。因为大多装备制造企业基于X86的体系架构,可以实现平滑的迁移。加上英特尔平台的移动终端由于体系开放,终端类型众多,就比较受到IT负责人的关注。因为用户可以从待机时间,耐用性,无线天线的灵敏度等多个方面,不同层面的要求衡量比较,从而最终采购到适合的产品。 因此综合来看,基于云计算的应用平台在装备制造企业中可以对生产前、生产中、生产后的各项工作进行预测和监控,打造生产制造透明化、高效化、智能化新模式,实现由传统制造业向智慧制造的转型,提升生产效率和管理水平。 物联网添砖加瓦 数字化模式的核心在于精益制造,其是在装备制造业中最重要的一个理念。将整个制造过程更加透明,用数据打破之前信息传递的不对称,信息的通常也可以规避更多问题,从而保证生产有序的进行。有了云端环境的支持,数字化工厂还需要具备什么要素? 其实数字化工场涉及的元素非常广泛,在各种元素融合在一起后,才能完成一个顶层设计。在很多企业主眼里数字化工厂只是几条自动化生产线,那就大错特错。这只是个一个基础,数字化工厂是让每一个环节都全部实现自动化,这也是装备制造业相比于电子制造业所欠缺的部分。 全自动无人焊接生产线 因此,曾有人说,想要让数字化工厂一步到位最简单直接的办法是开设新厂,但这对于中国装备制造业企业来说,成本投入太高,大家更多的是改造现有工厂,逐步实现数字化。老旧的生产线需要进行自动化的改造,并使用信息化的手段,例如管理系统整合底层生产线、条形码、RFID等,同时整合上游ERP、CRM、PLM等系统。 有专家总结,未来的装备制造企业的数字化工厂要包含三部分,一是智能化的生产过程,这里面将来会把云的触角伸展到上面;二是智能化的仓储物流,其实现在制造业制约发展最大的瓶颈就是信息的不对称,因为在装备制造业,大量的数据采集跟传递还是通过简易的Excel表形式,这些数据真正传递到有效部门有大量的延迟,这样会引发出大量的质量问题、产量问题,甚至是影响到客户满意度;三是智能加工中心的生产线。 以上三个部分,数据采集和分析都是关键因素。因此物联网技术的应用,可能是除了云端环境外,数字化工厂最离不开的一个手段。而且物联网技术不仅要求有硬件的植入,也需要软件的配合。以英特尔的IoT平台为例,它采取的架构就是以X86为基础,采用Wind River全新边缘设备管理软件,帮助设备进行配置、迁移文件、捕捉和分析数据等。 有了云端计算环境,有了物联网进行连接和数据收集。接下来就是装备制造业的问题就在于如何进行数据分析。英特尔是一个高科技公司,其所生产的的芯片更是一个高精度制造业产品,所以英特尔对数据的重要性有非常深刻的体会。 英特尔产品(成都)有限公司制造信息部总经理钱静波在12月份的中国制造千人会(MIC1000)就提到数据对于数字化工厂的重要性。他认为,第一部分就是能实现实时流程控制,在快速响应的数字化工厂中,设备一旦报警会立刻进行处理。第二,优化生产流程。第三,基于预测的设备维护优化。第四,普及自动化和机械控制提高生产速度。而这些都基于物联网和数据分析的能力。 当然,可能需要再次强调的是,远程云端(服务器,数据中心等软硬环境)的支持依然是最首要的基础。数字化工厂的建设和改造对于装备制造业的整体提升不言而喻,但是数字化工厂和传统工厂的区别太过巨大,践行之路必定需要解决很多具体问题,而且由于结合了互联网这样一个重要出口,很多技术问题最后会上升到商业模式问题。全球著名的装备制造业企业徐工集团的首席信息官、徐工信息技术股份有限公司总经理张启亮认为,从“互联网+工程机械”来看,就体现在研发的数字化、生产制造智能化、营销互联网化、售后服务智能化、产品功能智能化、后市场管理移动化等多个方面。 英特尔是工业互联网联盟的成员单位,英特尔中国区总经理夏乐蓓之前也表示,第三次工业革命时代有很多我们难以预料的新挑战,说得容易做起来难。不过对于这场数字化浪潮的结果,无论是作为提供IT手段的公司,还是本身就是高精尖制造业企业,夏乐培还是非常乐观的,从英特尔的角度看,“是有能力提供这样的技术,让中国更好地利用互联网时代带来的这些新机遇的”。 原文发布时间为:2016-7-14 本文作者:王聪彬 本文来自云栖社区合作伙伴至顶网,了解相关信息可以关注至顶网

优秀的个人博客,低调大师

Python数据分析实战:链家二手房数据爬取与房价预测全流程

在数据驱动的商业决策中,爬虫(数据采集)、数据分析(清洗与探索)和数据挖掘(建模预测)构成了完整的技术闭环。本文以链家二手房为实战目标,从零开始搭建一个可落地的房价预测系统。文章将涵盖:动态反爬策略、数据清洗与特征工程、多模型对比调优、以及基于聚类的地理区域分析。所有代码均可在Python 3.9+环境下运行,并附有完整项目结构,确保“可复现、可扩展、可落地”。

资源下载

更多资源
Nacos

Nacos

Nacos /nɑ:kəʊs/ 是 Dynamic Naming and Configuration Service 的首字母简称,一个易于构建 AI Agent 应用的动态服务发现、配置管理和AI智能体管理平台。Nacos 致力于帮助您发现、配置和管理微服务及AI智能体应用。Nacos 提供了一组简单易用的特性集,帮助您快速实现动态服务发现、服务配置、服务元数据、流量管理。Nacos 帮助您更敏捷和容易地构建、交付和管理微服务平台。

Spring

Spring

Spring框架(Spring Framework)是由Rod Johnson于2002年提出的开源Java企业级应用框架,旨在通过使用JavaBean替代传统EJB实现方式降低企业级编程开发的复杂性。该框架基于简单性、可测试性和松耦合性设计理念,提供核心容器、应用上下文、数据访问集成等模块,支持整合Hibernate、Struts等第三方框架,其适用范围不仅限于服务器端开发,绝大多数Java应用均可从中受益。

Sublime Text

Sublime Text

Sublime Text具有漂亮的用户界面和强大的功能,例如代码缩略图,Python的插件,代码段等。还可自定义键绑定,菜单和工具栏。Sublime Text 的主要功能包括:拼写检查,书签,完整的 Python API , Goto 功能,即时项目切换,多选择,多窗口等等。Sublime Text 是一个跨平台的编辑器,同时支持Windows、Linux、Mac OS X等操作系统。

WebStorm

WebStorm

WebStorm 是jetbrains公司旗下一款JavaScript 开发工具。目前已经被广大中国JS开发者誉为“Web前端开发神器”、“最强大的HTML5编辑器”、“最智能的JavaScript IDE”等。与IntelliJ IDEA同源,继承了IntelliJ IDEA强大的JS部分的功能。

用户登录
用户注册